forked from qt-creator/qt-creator
zeroconf: windows support, avahi improvements, less messages
* support windows without apple bonjour installed * avahi with autorefresh * less spurious updates (messages when nothing actually changes) * quickly give up on connecting to daemon the first time * added startedBrowsing signal Change-Id: I8a29d94040fa6ffae318c98782120123093d6616 Reviewed-by: Jarek Kobus <jaroslaw.kobus@nokia.com>
This commit is contained in:
@@ -52,6 +52,7 @@
|
|||||||
#include <avahi-common/error.h>
|
#include <avahi-common/error.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
|
|
||||||
namespace ZeroConf {
|
namespace ZeroConf {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -70,6 +71,7 @@ extern "C" void cAvahiBrowseReply(
|
|||||||
AvahiServiceBrowser * /*b*/, AvahiIfIndex interface, AvahiProtocol /*protocol*/,
|
AvahiServiceBrowser * /*b*/, AvahiIfIndex interface, AvahiProtocol /*protocol*/,
|
||||||
AvahiBrowserEvent event, const char *name, const char *type, const char *domain,
|
AvahiBrowserEvent event, const char *name, const char *type, const char *domain,
|
||||||
AvahiLookupResultFlags /*flags*/, void* context);
|
AvahiLookupResultFlags /*flags*/, void* context);
|
||||||
|
extern "C" int cAvahiPollFunction(struct pollfd *ufds, unsigned int nfds, int timeout, void *userdata);
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
typedef const AvahiPoll* (*AvahiSimplePollGet)(AvahiSimplePoll *s);
|
typedef const AvahiPoll* (*AvahiSimplePollGet)(AvahiSimplePoll *s);
|
||||||
@@ -77,6 +79,7 @@ typedef AvahiSimplePoll *(*AvahiSimplePollNewPtr)(void);
|
|||||||
typedef int (*AvahiSimplePollIteratePtr)(AvahiSimplePoll *s, int sleep_time);
|
typedef int (*AvahiSimplePollIteratePtr)(AvahiSimplePoll *s, int sleep_time);
|
||||||
typedef void (*AvahiSimplePollQuitPtr)(AvahiSimplePoll *s);
|
typedef void (*AvahiSimplePollQuitPtr)(AvahiSimplePoll *s);
|
||||||
typedef void (*AvahiSimplePollFreePtr)(AvahiSimplePoll *s);
|
typedef void (*AvahiSimplePollFreePtr)(AvahiSimplePoll *s);
|
||||||
|
typedef void (*AvahiSimplePollSetFuncPtr)(AvahiSimplePoll *s, AvahiPollFunc func, void *userdata);
|
||||||
typedef AvahiClient* (*AvahiClientNewPtr)(
|
typedef AvahiClient* (*AvahiClientNewPtr)(
|
||||||
const AvahiPoll *poll_api, AvahiClientFlags flags, AvahiClientCallback callback,
|
const AvahiPoll *poll_api, AvahiClientFlags flags, AvahiClientCallback callback,
|
||||||
void *userdata, int *error);
|
void *userdata, int *error);
|
||||||
@@ -113,6 +116,7 @@ private:
|
|||||||
AvahiSimplePollIteratePtr m_simplePollIterate;
|
AvahiSimplePollIteratePtr m_simplePollIterate;
|
||||||
AvahiSimplePollQuitPtr m_simplePollQuit;
|
AvahiSimplePollQuitPtr m_simplePollQuit;
|
||||||
AvahiSimplePollFreePtr m_simplePollFree;
|
AvahiSimplePollFreePtr m_simplePollFree;
|
||||||
|
AvahiSimplePollSetFuncPtr m_simplePollSetFunc;
|
||||||
AvahiClientNewPtr m_clientNew;
|
AvahiClientNewPtr m_clientNew;
|
||||||
AvahiClientFreePtr m_clientFree;
|
AvahiClientFreePtr m_clientFree;
|
||||||
AvahiServiceBrowserNewPtr m_serviceBrowserNew;
|
AvahiServiceBrowserNewPtr m_serviceBrowserNew;
|
||||||
@@ -137,6 +141,7 @@ public:
|
|||||||
m_simplePollIterate = reinterpret_cast<AvahiSimplePollIteratePtr>(nativeLib.resolve("avahi_simple_poll_iterate"));
|
m_simplePollIterate = reinterpret_cast<AvahiSimplePollIteratePtr>(nativeLib.resolve("avahi_simple_poll_iterate"));
|
||||||
m_simplePollQuit = reinterpret_cast<AvahiSimplePollQuitPtr>(nativeLib.resolve("avahi_simple_poll_quit"));
|
m_simplePollQuit = reinterpret_cast<AvahiSimplePollQuitPtr>(nativeLib.resolve("avahi_simple_poll_quit"));
|
||||||
m_simplePollFree = reinterpret_cast<AvahiSimplePollFreePtr>(nativeLib.resolve("avahi_simple_poll_free"));
|
m_simplePollFree = reinterpret_cast<AvahiSimplePollFreePtr>(nativeLib.resolve("avahi_simple_poll_free"));
|
||||||
|
m_simplePollSetFunc = reinterpret_cast<AvahiSimplePollSetFuncPtr>(nativeLib.resolve("avahi_simple_poll_set_func"));
|
||||||
m_clientNew = reinterpret_cast<AvahiClientNewPtr>(nativeLib.resolve("avahi_client_new"));
|
m_clientNew = reinterpret_cast<AvahiClientNewPtr>(nativeLib.resolve("avahi_client_new"));
|
||||||
m_clientFree = reinterpret_cast<AvahiClientFreePtr>(nativeLib.resolve("avahi_client_free"));
|
m_clientFree = reinterpret_cast<AvahiClientFreePtr>(nativeLib.resolve("avahi_client_free"));
|
||||||
m_serviceBrowserNew = reinterpret_cast<AvahiServiceBrowserNewPtr>(nativeLib.resolve("avahi_service_browser_new"));
|
m_serviceBrowserNew = reinterpret_cast<AvahiServiceBrowserNewPtr>(nativeLib.resolve("avahi_service_browser_new"));
|
||||||
@@ -149,6 +154,7 @@ public:
|
|||||||
m_simplePollIterate = reinterpret_cast<AvahiSimplePollIteratePtr>(&avahi_simple_poll_iterate);
|
m_simplePollIterate = reinterpret_cast<AvahiSimplePollIteratePtr>(&avahi_simple_poll_iterate);
|
||||||
m_simplePollQuit = reinterpret_cast<AvahiSimplePollQuitPtr>(&avahi_simple_poll_quit);
|
m_simplePollQuit = reinterpret_cast<AvahiSimplePollQuitPtr>(&avahi_simple_poll_quit);
|
||||||
m_simplePollFree = reinterpret_cast<AvahiSimplePollFreePtr>(&avahi_simple_poll_free);
|
m_simplePollFree = reinterpret_cast<AvahiSimplePollFreePtr>(&avahi_simple_poll_free);
|
||||||
|
m_simplePollSetFunc = reinterpret_cast<AvahiSimplePollSetFuncPtr>(&avahi_simple_poll_set_func);
|
||||||
m_clientNew = reinterpret_cast<AvahiClientNewPtr>(&avahi_client_new);
|
m_clientNew = reinterpret_cast<AvahiClientNewPtr>(&avahi_client_new);
|
||||||
m_clientFree = reinterpret_cast<AvahiClientFreePtr>(&avahi_client_free);
|
m_clientFree = reinterpret_cast<AvahiClientFreePtr>(&avahi_client_free);
|
||||||
m_serviceBrowserNew = reinterpret_cast<AvahiServiceBrowserNewPtr>(&avahi_service_browser_new);
|
m_serviceBrowserNew = reinterpret_cast<AvahiServiceBrowserNewPtr>(&avahi_service_browser_new);
|
||||||
@@ -162,6 +168,7 @@ public:
|
|||||||
if (!m_simplePollIterate) qDebug() << name() << " has null m_simplePollIterate";
|
if (!m_simplePollIterate) qDebug() << name() << " has null m_simplePollIterate";
|
||||||
if (!m_simplePollQuit) qDebug() << name() << " has null m_simplePollQuit";
|
if (!m_simplePollQuit) qDebug() << name() << " has null m_simplePollQuit";
|
||||||
if (!m_simplePollFree) qDebug() << name() << " has null m_simplePollFree";
|
if (!m_simplePollFree) qDebug() << name() << " has null m_simplePollFree";
|
||||||
|
if (!m_simplePollSetFunc) qDebug() << name() << " has null m_simplePollSetFunc";
|
||||||
if (!m_clientNew) qDebug() << name() << " has null m_clientNew";
|
if (!m_clientNew) qDebug() << name() << " has null m_clientNew";
|
||||||
if (!m_clientFree) qDebug() << name() << " has null m_clientFree";
|
if (!m_clientFree) qDebug() << name() << " has null m_clientFree";
|
||||||
if (!m_serviceBrowserNew) qDebug() << name() << " has null m_serviceBrowserNew";
|
if (!m_serviceBrowserNew) qDebug() << name() << " has null m_serviceBrowserNew";
|
||||||
@@ -286,6 +293,7 @@ public:
|
|||||||
return kDNSServiceErr_Unknown;
|
return kDNSServiceErr_Unknown;
|
||||||
//avahi_strerror(avahi_client_errno(client));
|
//avahi_strerror(avahi_client_errno(client));
|
||||||
}
|
}
|
||||||
|
browser->activateAutoRefresh();
|
||||||
return kDNSServiceErr_NoError;
|
return kDNSServiceErr_NoError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +305,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RunLoopStatus processOneEvent(ConnectionRef cRef, qint64 maxLockMs) {
|
RunLoopStatus processOneEvent(MainConnection *, ConnectionRef cRef, qint64 maxLockMs) {
|
||||||
if (!m_simplePollIterate)
|
if (!m_simplePollIterate)
|
||||||
return ProcessedFailure;
|
return ProcessedFailure;
|
||||||
MyAvahiConnection *connection = reinterpret_cast<MyAvahiConnection *>(cRef);
|
MyAvahiConnection *connection = reinterpret_cast<MyAvahiConnection *>(cRef);
|
||||||
@@ -309,11 +317,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
RunLoopStatus processOneEventBlock(ConnectionRef cRef) {
|
RunLoopStatus processOneEventBlock(ConnectionRef cRef) {
|
||||||
return processOneEvent(cRef,-1);
|
return processOneEvent(NULL,cRef,-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
DNSServiceErrorType createConnection(ConnectionRef *sdRef) {
|
DNSServiceErrorType createConnection(MainConnection *mainConnection, ConnectionRef *sdRef) {
|
||||||
if (!m_simplePollNew || !m_clientNew)
|
if (!m_simplePollNew || !m_clientNew || !m_simplePollSetFunc)
|
||||||
return kDNSServiceErr_Unknown;
|
return kDNSServiceErr_Unknown;
|
||||||
MyAvahiConnection *connection = new MyAvahiConnection;
|
MyAvahiConnection *connection = new MyAvahiConnection;
|
||||||
connection->lib = this;
|
connection->lib = this;
|
||||||
@@ -327,6 +335,8 @@ public:
|
|||||||
delete connection;
|
delete connection;
|
||||||
return kDNSServiceErr_Unknown;
|
return kDNSServiceErr_Unknown;
|
||||||
}
|
}
|
||||||
|
typedef void (*AvahiSimplePollSetFuncPtr)(AvahiSimplePoll *s, AvahiPollFunc func, void *userdata);
|
||||||
|
m_simplePollSetFunc(connection->simple_poll, &cAvahiPollFunction, mainConnection);
|
||||||
/* Allocate a new client */
|
/* Allocate a new client */
|
||||||
int error;
|
int error;
|
||||||
connection->client = m_clientNew(m_simplePollGet(connection->simple_poll),
|
connection->client = m_clientNew(m_simplePollGet(connection->simple_poll),
|
||||||
@@ -525,6 +535,20 @@ extern "C" void cAvahiBrowseReply(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" int cAvahiPollFunction(struct pollfd *ufds, unsigned int nfds, int timeout, void *userdata)
|
||||||
|
{
|
||||||
|
MainConnection *mainConnection = static_cast<MainConnection *>(userdata);
|
||||||
|
QMutex *lock = 0;
|
||||||
|
if (mainConnection)
|
||||||
|
lock = mainConnection->mainThreadLock();
|
||||||
|
if (lock)
|
||||||
|
lock->unlock();
|
||||||
|
int res=poll(ufds,nfds,timeout);
|
||||||
|
if (lock)
|
||||||
|
lock->lock();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ZeroConf
|
} // namespace ZeroConf
|
||||||
|
|
||||||
|
@@ -138,6 +138,10 @@ public:
|
|||||||
m_createConnection = reinterpret_cast<CreateConnectionPtr>(&DNSServiceCreateConnection);
|
m_createConnection = reinterpret_cast<CreateConnectionPtr>(&DNSServiceCreateConnection);
|
||||||
m_refSockFD = reinterpret_cast<RefSockFDPtr>(&DNSServiceRefSockFD);
|
m_refSockFD = reinterpret_cast<RefSockFDPtr>(&DNSServiceRefSockFD);
|
||||||
#endif
|
#endif
|
||||||
|
if (m_isOk && m_getAddrInfo == 0) {
|
||||||
|
m_isOk = false;
|
||||||
|
m_errorMsg = tr("*WARNING* DnsSdZConfLib detected an obsolete version of Apple Bonjour, either disable/uninstall it or upgrade it. Otherwise zeroconf will fail.");
|
||||||
|
}
|
||||||
if (DEBUG_ZEROCONF){
|
if (DEBUG_ZEROCONF){
|
||||||
if (m_refDeallocate == 0) qDebug() << QLatin1String("DnsSdZConfLib.m_refDeallocate == 0");
|
if (m_refDeallocate == 0) qDebug() << QLatin1String("DnsSdZConfLib.m_refDeallocate == 0");
|
||||||
if (m_resolve == 0) qDebug() << QLatin1String("DnsSdZConfLib.m_resolve == 0");
|
if (m_resolve == 0) qDebug() << QLatin1String("DnsSdZConfLib.m_resolve == 0");
|
||||||
@@ -284,7 +288,7 @@ public:
|
|||||||
return ProcessedOk;
|
return ProcessedOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
DNSServiceErrorType createConnection(ConnectionRef *sdRef)
|
DNSServiceErrorType createConnection(MainConnection *, ConnectionRef *sdRef)
|
||||||
{
|
{
|
||||||
if (m_createConnection == 0) return kDNSServiceErr_Unsupported;
|
if (m_createConnection == 0) return kDNSServiceErr_Unsupported;
|
||||||
return m_createConnection(reinterpret_cast<DNSServiceRef *>(sdRef));
|
return m_createConnection(reinterpret_cast<DNSServiceRef *>(sdRef));
|
||||||
@@ -299,7 +303,6 @@ public:
|
|||||||
|
|
||||||
ZConfLib::Ptr ZConfLib::createDnsSdLib(const QString &libName, ZConfLib::Ptr fallback) {
|
ZConfLib::Ptr ZConfLib::createDnsSdLib(const QString &libName, ZConfLib::Ptr fallback) {
|
||||||
return ZConfLib::Ptr(new DnsSdZConfLib(libName, fallback));
|
return ZConfLib::Ptr(new DnsSdZConfLib(libName, fallback));
|
||||||
return fallback;
|
|
||||||
}
|
}
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ZeroConf
|
} // namespace ZeroConf
|
||||||
|
1518
src/libs/zeroconf/embed/CommonServices.h
Normal file
1518
src/libs/zeroconf/embed/CommonServices.h
Normal file
File diff suppressed because it is too large
Load Diff
3075
src/libs/zeroconf/embed/DebugServices.c
Normal file
3075
src/libs/zeroconf/embed/DebugServices.c
Normal file
File diff suppressed because it is too large
Load Diff
1607
src/libs/zeroconf/embed/DebugServices.h
Normal file
1607
src/libs/zeroconf/embed/DebugServices.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -40,17 +40,16 @@ namespace ZeroConf { namespace embeddedLib {
|
|||||||
static int gDaemonErr = kDNSServiceErr_NoError;
|
static int gDaemonErr = kDNSServiceErr_NoError;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
||||||
#define _SSIZE_T
|
#define _SSIZE_T
|
||||||
#include <CommonServices.h>
|
#include "embed/CommonServices.h"
|
||||||
#include <DebugServices.h>
|
#include "embed/DebugServices.h"
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define sockaddr_mdns sockaddr_in
|
#define sockaddr_mdns sockaddr_in
|
||||||
#define AF_MDNS AF_INET
|
#define AF_MDNS AF_INET
|
||||||
@@ -61,7 +60,7 @@ extern "C" {
|
|||||||
// Disable warning: "nonstandard extension, function/data pointer conversion in expression"
|
// Disable warning: "nonstandard extension, function/data pointer conversion in expression"
|
||||||
#pragma warning(disable:4152)
|
#pragma warning(disable:4152)
|
||||||
|
|
||||||
extern BOOL IsSystemServiceDisabled();
|
//extern BOOL IsSystemServiceDisabled();
|
||||||
|
|
||||||
#define sleep(X) Sleep((X) * 1000)
|
#define sleep(X) Sleep((X) * 1000)
|
||||||
#define NOT_HAVE_SA_LEN
|
#define NOT_HAVE_SA_LEN
|
||||||
@@ -83,6 +82,7 @@ namespace ZeroConf { namespace embeddedLib {
|
|||||||
if ( buffer ) { vsprintf( buffer, message, args ); OutputDebugStringA( buffer ); free( buffer ); }
|
if ( buffer ) { vsprintf( buffer, message, args ); OutputDebugStringA( buffer ); free( buffer ); }
|
||||||
WSASetLastError( err );
|
WSASetLastError( err );
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <sys/fcntl.h> // For O_RDWR etc.
|
#include <sys/fcntl.h> // For O_RDWR etc.
|
||||||
@@ -112,6 +112,7 @@ namespace ZeroConf { namespace embeddedLib {
|
|||||||
#define CTL_PATH_PREFIX "/var/tmp/dnssd_result_socket."
|
#define CTL_PATH_PREFIX "/var/tmp/dnssd_result_socket."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ipc_msg_hdr ipc_hdr;
|
ipc_msg_hdr ipc_hdr;
|
||||||
@@ -427,6 +428,7 @@ static void FreeDNSServiceOp(DNSServiceOp *x)
|
|||||||
// Return a connected service ref (deallocate with DNSServiceRefDeallocate)
|
// Return a connected service ref (deallocate with DNSServiceRefDeallocate)
|
||||||
static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags flags, uint32_t op, ProcessReplyFn ProcessReply, void *AppCallback, void *AppContext)
|
static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags flags, uint32_t op, ProcessReplyFn ProcessReply, void *AppCallback, void *AppContext)
|
||||||
{
|
{
|
||||||
|
static int quickCheck = 1;
|
||||||
#if APPLE_OSX_mDNSResponder
|
#if APPLE_OSX_mDNSResponder
|
||||||
int NumTries = DNSSD_CLIENT_MAXTRIES;
|
int NumTries = DNSSD_CLIENT_MAXTRIES;
|
||||||
#else
|
#else
|
||||||
@@ -462,7 +464,7 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f
|
|||||||
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { *ref = NULL; return kDNSServiceErr_ServiceNotRunning; }
|
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { *ref = NULL; return kDNSServiceErr_ServiceNotRunning; }
|
||||||
}
|
}
|
||||||
// <rdar://problem/4096913> If the system service is disabled, we only want to try to connect once
|
// <rdar://problem/4096913> If the system service is disabled, we only want to try to connect once
|
||||||
if (IsSystemServiceDisabled()) NumTries = DNSSD_CLIENT_MAXTRIES;
|
//if (IsSystemServiceDisabled()) NumTries = DNSSD_CLIENT_MAXTRIES;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sdr = static_cast<DNSServiceOp*>(malloc(sizeof(DNSServiceOp)));
|
sdr = static_cast<DNSServiceOp*>(malloc(sizeof(DNSServiceOp)));
|
||||||
@@ -543,8 +545,10 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f
|
|||||||
// daemon is still coming up. Rather than fail here, we'll wait a bit and try again.
|
// daemon is still coming up. Rather than fail here, we'll wait a bit and try again.
|
||||||
// If, after four seconds, we still can't connect to the daemon,
|
// If, after four seconds, we still can't connect to the daemon,
|
||||||
// then we give up and return a failure code.
|
// then we give up and return a failure code.
|
||||||
if (++NumTries < DNSSD_CLIENT_MAXTRIES) sleep(1); // Sleep a bit, then try again
|
if (++NumTries < DNSSD_CLIENT_MAXTRIES && !quickCheck) sleep(1); // Sleep a bit, then try again
|
||||||
else { dnssd_close(sdr->sockfd); FreeDNSServiceOp(sdr); return kDNSServiceErr_ServiceNotRunning; }
|
else {
|
||||||
|
quickCheck = 0;
|
||||||
|
dnssd_close(sdr->sockfd); FreeDNSServiceOp(sdr); return kDNSServiceErr_ServiceNotRunning; }
|
||||||
}
|
}
|
||||||
//printf("ConnectToServer opened socket %d\n", sdr->sockfd);
|
//printf("ConnectToServer opened socket %d\n", sdr->sockfd);
|
||||||
}
|
}
|
||||||
|
@@ -44,6 +44,10 @@
|
|||||||
#define EMBEDDED_LIB
|
#define EMBEDDED_LIB
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
#define EMBEDDED_LIB
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef EMBEDDED_LIB
|
#ifdef EMBEDDED_LIB
|
||||||
#include "embed/dnssd_ipc.c"
|
#include "embed/dnssd_ipc.c"
|
||||||
#include "embed/dnssd_clientlib.c"
|
#include "embed/dnssd_clientlib.c"
|
||||||
@@ -204,7 +208,7 @@ public:
|
|||||||
return ProcessedOk;
|
return ProcessedOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
DNSServiceErrorType createConnection(ConnectionRef *sdRef)
|
DNSServiceErrorType createConnection(MainConnection *, ConnectionRef *sdRef)
|
||||||
{
|
{
|
||||||
return embeddedLib::DNSServiceCreateConnection(reinterpret_cast<DNSServiceRef*>(sdRef));
|
return embeddedLib::DNSServiceCreateConnection(reinterpret_cast<DNSServiceRef*>(sdRef));
|
||||||
}
|
}
|
||||||
|
@@ -135,16 +135,26 @@ public:
|
|||||||
const QString &dnsSdDaemonPath);
|
const QString &dnsSdDaemonPath);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static const char *defaultmDnsSdLibName;
|
||||||
|
static const char *defaultmDNSDaemonName;
|
||||||
QMutex m_lock;
|
QMutex m_lock;
|
||||||
ZConfLib::Ptr m_defaultLib;
|
ZConfLib::Ptr m_defaultLib;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(ZeroConfLib, zeroConfLibInstance)
|
Q_GLOBAL_STATIC(ZeroConfLib, zeroConfLibInstance)
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
const char *ZeroConfLib::defaultmDnsSdLibName = "dnssd";
|
||||||
|
const char *ZeroConfLib::defaultmDNSDaemonName = "mdnssd.exe";
|
||||||
|
#else
|
||||||
|
const char *ZeroConfLib::defaultmDnsSdLibName = "dns_sd";
|
||||||
|
const char *ZeroConfLib::defaultmDNSDaemonName = "mdnssd";
|
||||||
|
#endif
|
||||||
|
|
||||||
ZeroConfLib::ZeroConfLib(): m_lock(QMutex::Recursive),
|
ZeroConfLib::ZeroConfLib(): m_lock(QMutex::Recursive),
|
||||||
m_defaultLib(ZConfLib::createAvahiLib(QLatin1String("avahi-client"),
|
m_defaultLib(ZConfLib::createAvahiLib(QLatin1String("avahi-client"),
|
||||||
ZConfLib::createDnsSdLib(QLatin1String("dns_sd"),
|
ZConfLib::createDnsSdLib(QLatin1String(defaultmDnsSdLibName),
|
||||||
ZConfLib::createEmbeddedLib(QLatin1String("mdnssd")))))
|
ZConfLib::createEmbeddedLib(QLatin1String(defaultmDNSDaemonName)))))
|
||||||
{
|
{
|
||||||
qRegisterMetaType<ZeroConf::Service::ConstPtr>("ZeroConf::Service::ConstPtr");
|
qRegisterMetaType<ZeroConf::Service::ConstPtr>("ZeroConf::Service::ConstPtr");
|
||||||
qRegisterMetaType<ZeroConf::ErrorMessage::SeverityLevel>("ZeroConf::ErrorMessage::SeverityLevel");
|
qRegisterMetaType<ZeroConf::ErrorMessage::SeverityLevel>("ZeroConf::ErrorMessage::SeverityLevel");
|
||||||
@@ -259,7 +269,24 @@ Service::~Service()
|
|||||||
delete m_host;
|
delete m_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEROCONFSHARED_EXPORT QDebug operator<<(QDebug dbg, const Service &service)
|
bool Service::operator==(const Service &o) const {
|
||||||
|
bool eq = m_fullName == o.m_fullName
|
||||||
|
&& m_name == o.m_name && m_type == o.m_type
|
||||||
|
&& m_domain == o.m_domain && m_port == o.m_port
|
||||||
|
&& m_txtRecord == o.m_txtRecord && m_interfaceNr == o.m_interfaceNr
|
||||||
|
&& m_outdated == m_outdated;
|
||||||
|
if (eq) {
|
||||||
|
if (m_host != o.m_host) {
|
||||||
|
if (m_host == 0 || o.m_host == 0)
|
||||||
|
return false;
|
||||||
|
return m_host->hostName() == o.m_host->hostName()
|
||||||
|
&& m_host->addresses() == o.m_host->addresses();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return eq;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug dbg, const Service &service)
|
||||||
{
|
{
|
||||||
dbg.maybeSpace() << "Service{ name:" << service.name() << ", "
|
dbg.maybeSpace() << "Service{ name:" << service.name() << ", "
|
||||||
<< "type:" << service.type() << ", domain:" << service.domain() << ", "
|
<< "type:" << service.type() << ", domain:" << service.domain() << ", "
|
||||||
@@ -293,6 +320,16 @@ ZEROCONFSHARED_EXPORT QDebug operator<<(QDebug dbg, const Service &service)
|
|||||||
dbg << " interfaceNr:" << service.interfaceNr() << ", outdated:" << service.outdated() << " }";
|
dbg << " interfaceNr:" << service.interfaceNr() << ", outdated:" << service.outdated() << " }";
|
||||||
return dbg.space();
|
return dbg.space();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug dbg, const Service::ConstPtr &service){
|
||||||
|
if (service.data() == 0){
|
||||||
|
dbg << "Service{*NULL*}";
|
||||||
|
} else {
|
||||||
|
dbg << *service.data();
|
||||||
|
}
|
||||||
|
return dbg;
|
||||||
|
}
|
||||||
|
|
||||||
// inline methods
|
// inline methods
|
||||||
/*!
|
/*!
|
||||||
\fn bool Service::outdated() const
|
\fn bool Service::outdated() const
|
||||||
@@ -369,16 +406,17 @@ void ServiceBrowser::startBrowsing(qint32 interfaceIndex)
|
|||||||
/// create a new brower for the given service type
|
/// create a new brower for the given service type
|
||||||
ServiceBrowser::ServiceBrowser(const QString &serviceType, const QString &domain,
|
ServiceBrowser::ServiceBrowser(const QString &serviceType, const QString &domain,
|
||||||
AddressesSetting addressesSetting, QObject *parent)
|
AddressesSetting addressesSetting, QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent), timer(0),
|
||||||
d(new ServiceBrowserPrivate(serviceType, domain, addressesSetting == RequireAddresses,
|
d(new ServiceBrowserPrivate(serviceType, domain, addressesSetting == RequireAddresses,
|
||||||
MainConnectionPtr()))
|
MainConnectionPtr()))
|
||||||
{
|
{
|
||||||
|
connect(this,SIGNAL(activateAutoRefresh()),this,SLOT(autoRefresh()));
|
||||||
d->q = this;
|
d->q = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceBrowser::ServiceBrowser(const MainConnectionPtr &mainConnection, const QString &serviceType,
|
ServiceBrowser::ServiceBrowser(const MainConnectionPtr &mainConnection, const QString &serviceType,
|
||||||
const QString &domain, AddressesSetting addressesSetting, QObject *parent)
|
const QString &domain, AddressesSetting addressesSetting, QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent), timer(0),
|
||||||
d(new ServiceBrowserPrivate(serviceType, domain, addressesSetting == RequireAddresses,
|
d(new ServiceBrowserPrivate(serviceType, domain, addressesSetting == RequireAddresses,
|
||||||
mainConnection))
|
mainConnection))
|
||||||
{
|
{
|
||||||
@@ -399,6 +437,11 @@ MainConnectionPtr ServiceBrowser::mainConnection() const
|
|||||||
/// stops browsing, but does not delete all services found
|
/// stops browsing, but does not delete all services found
|
||||||
void ServiceBrowser::stopBrowsing()
|
void ServiceBrowser::stopBrowsing()
|
||||||
{
|
{
|
||||||
|
if (timer) {
|
||||||
|
timer->stop();
|
||||||
|
delete timer;
|
||||||
|
timer = 0;
|
||||||
|
}
|
||||||
d->stopBrowsing();
|
d->stopBrowsing();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,6 +495,16 @@ void ServiceBrowser::reconfirmService(Service::ConstPtr service)
|
|||||||
d->reconfirmService(service);
|
d->reconfirmService(service);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServiceBrowser::autoRefresh()
|
||||||
|
{
|
||||||
|
QMutexLocker l(d->mainConnection->lock());
|
||||||
|
if (!timer) {
|
||||||
|
timer = new QTimer(this);
|
||||||
|
connect(timer,SIGNAL(timeout()),this,SLOT(triggerRefresh()));
|
||||||
|
timer->start(5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// signals
|
// signals
|
||||||
/*!
|
/*!
|
||||||
\fn void ServiceBrowser::serviceChanged(
|
\fn void ServiceBrowser::serviceChanged(
|
||||||
@@ -485,6 +538,24 @@ void ServiceBrowser::reconfirmService(Service::ConstPtr service)
|
|||||||
services(), use this signal, not serviceChanged(), serviceAdded() or serviceRemoved() to know
|
services(), use this signal, not serviceChanged(), serviceAdded() or serviceRemoved() to know
|
||||||
about changes to the list.
|
about changes to the list.
|
||||||
*/
|
*/
|
||||||
|
/*!
|
||||||
|
\fn void errorMessage(ZeroConf::ErrorMessage::SeverityLevel severity, const QString &msg, ZeroConf::ServiceBrowser *browser)
|
||||||
|
|
||||||
|
This signal is called every time a warning or error is emitted (for example when a library
|
||||||
|
cannot be used and another one has to be used). Zeroconf will still work if severity < FailureLevel.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
\fn void hadFailure(const QList<ZeroConf::ErrorMessage> &messages, ZeroConf::ServiceBrowser *browser)
|
||||||
|
|
||||||
|
This signal is emitted only when a full failure has happened, and all the previous errors/attempts to set up zeroconf
|
||||||
|
are passed in messages.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
\fn void startedBrowsing(ZeroConf::ServiceBrowser *browser)
|
||||||
|
|
||||||
|
This signal is emitted when browsing has actually started.
|
||||||
|
One can rely on either startedBrowsing or hadFailure to be emitted.
|
||||||
|
*/
|
||||||
|
|
||||||
// ----------------- library initialization impl -----------------
|
// ----------------- library initialization impl -----------------
|
||||||
/*!
|
/*!
|
||||||
@@ -631,25 +702,32 @@ QString ServiceGatherer::fullName(){
|
|||||||
return currentService->fullName();
|
return currentService->fullName();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceGatherer::enactServiceChange()
|
bool ServiceGatherer::enactServiceChange()
|
||||||
{
|
{
|
||||||
if (DEBUG_ZEROCONF)
|
if (DEBUG_ZEROCONF)
|
||||||
qDebug() << "ServiceGatherer::enactServiceChange() for service "
|
qDebug() << "ServiceGatherer::enactServiceChange() for service "
|
||||||
<< currentService->fullName();
|
<< currentService->fullName();
|
||||||
if (currentServiceCanBePublished()) {
|
if (currentServiceCanBePublished()) {
|
||||||
|
if ((publishedService.data() == 0 && currentService == 0)
|
||||||
|
|| (publishedService.data() != 0 && currentService != 0
|
||||||
|
&& *publishedService == *currentService))
|
||||||
|
return false;
|
||||||
Service::Ptr nService = Service::Ptr(currentService);
|
Service::Ptr nService = Service::Ptr(currentService);
|
||||||
serviceBrowser->serviceChanged(publishedService, nService, serviceBrowser->q);
|
|
||||||
if (publishedService) {
|
if (publishedService) {
|
||||||
|
publishedService->invalidate();
|
||||||
serviceBrowser->nextActiveServices.removeOne(publishedService);
|
serviceBrowser->nextActiveServices.removeOne(publishedService);
|
||||||
serviceBrowser->serviceRemoved(publishedService, serviceBrowser->q);
|
serviceBrowser->serviceRemoved(publishedService, serviceBrowser->q);
|
||||||
}
|
}
|
||||||
|
serviceBrowser->serviceChanged(publishedService, nService, serviceBrowser->q);
|
||||||
publishedService = nService;
|
publishedService = nService;
|
||||||
if (nService) {
|
if (nService) {
|
||||||
serviceBrowser->nextActiveServices.append(nService);
|
serviceBrowser->nextActiveServices.append(nService);
|
||||||
serviceBrowser->serviceAdded(nService, serviceBrowser->q);
|
serviceBrowser->serviceAdded(nService, serviceBrowser->q);
|
||||||
currentService = new Service(*currentService);
|
currentService = new Service(*currentService);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceGatherer::retireService()
|
void ServiceGatherer::retireService()
|
||||||
@@ -660,8 +738,9 @@ void ServiceGatherer::retireService()
|
|||||||
<< currentService->fullName();
|
<< currentService->fullName();
|
||||||
Service::Ptr nService;
|
Service::Ptr nService;
|
||||||
serviceBrowser->nextActiveServices.removeOne(publishedService);
|
serviceBrowser->nextActiveServices.removeOne(publishedService);
|
||||||
serviceBrowser->serviceChanged(publishedService, nService, serviceBrowser->q);
|
publishedService->invalidate();
|
||||||
serviceBrowser->serviceRemoved(publishedService, serviceBrowser->q);
|
serviceBrowser->serviceRemoved(publishedService, serviceBrowser->q);
|
||||||
|
serviceBrowser->serviceChanged(publishedService, nService, serviceBrowser->q);
|
||||||
publishedService = nService;
|
publishedService = nService;
|
||||||
} else if (DEBUG_ZEROCONF){
|
} else if (DEBUG_ZEROCONF){
|
||||||
qDebug() << "ServiceGatherer::retireService() for non published service "
|
qDebug() << "ServiceGatherer::retireService() for non published service "
|
||||||
@@ -897,7 +976,6 @@ void ServiceGatherer::serviceResolveReply(DNSServiceFlags fl
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (publishedService) publishedService->invalidate(); // delay this to enactServiceChange?
|
|
||||||
serviceBrowser->updateFlowStatusForFlags(flags);
|
serviceBrowser->updateFlowStatusForFlags(flags);
|
||||||
uint16_t nKeys = txtRecordGetCount(txtLen, rawTxtRecord);
|
uint16_t nKeys = txtRecordGetCount(txtLen, rawTxtRecord);
|
||||||
for (uint16_t i = 0; i < nKeys; ++i){
|
for (uint16_t i = 0; i < nKeys; ++i){
|
||||||
@@ -1041,7 +1119,7 @@ void ServiceGatherer::addrReply(DNSServiceFlags flags,
|
|||||||
const struct sockaddr *address,
|
const struct sockaddr *address,
|
||||||
uint32_t /*ttl*/) // should we use this???
|
uint32_t /*ttl*/) // should we use this???
|
||||||
{
|
{
|
||||||
if (errorCode != kDNSServiceErr_NoError){
|
if (errorCode != kDNSServiceErr_NoError) {
|
||||||
if (errorCode == kDNSServiceErr_Timeout){
|
if (errorCode == kDNSServiceErr_Timeout){
|
||||||
if ((status & AddrConnectionSuccess) == 0){
|
if ((status & AddrConnectionSuccess) == 0){
|
||||||
qDebug() << "ServiceBrowser " << serviceBrowser->serviceType
|
qDebug() << "ServiceBrowser " << serviceBrowser->serviceType
|
||||||
@@ -1088,8 +1166,12 @@ void ServiceGatherer::addrReply(DNSServiceFlags flags,
|
|||||||
} else {
|
} else {
|
||||||
if (!addrNow.contains(newAddr)){
|
if (!addrNow.contains(newAddr)){
|
||||||
switch (newAddr.protocol()){
|
switch (newAddr.protocol()){
|
||||||
case QAbstractSocket::IPv6Protocol:
|
#ifdef Q_OS_WIN
|
||||||
addrNow.insert(0, newAddr); // prefers IPv6 addresses
|
case QAbstractSocket::IPv4Protocol: // prefers IPv4 addresses
|
||||||
|
#else
|
||||||
|
case QAbstractSocket::IPv6Protocol: // prefers IPv6 addresses
|
||||||
|
#endif
|
||||||
|
addrNow.insert(0, newAddr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
addrNow.append(newAddr);
|
addrNow.append(newAddr);
|
||||||
@@ -1239,6 +1321,7 @@ void ServiceBrowserPrivate::maybeUpdateLists()
|
|||||||
qint64 now = QDateTime::currentMSecsSinceEpoch();
|
qint64 now = QDateTime::currentMSecsSinceEpoch();
|
||||||
QList<QString>::iterator i = knownServices.begin(), endi = knownServices.end();
|
QList<QString>::iterator i = knownServices.begin(), endi = knownServices.end();
|
||||||
QMap<QString, ServiceGatherer::Ptr>::iterator j = gatherers.begin();
|
QMap<QString, ServiceGatherer::Ptr>::iterator j = gatherers.begin();
|
||||||
|
bool hasServicesChanges = false;
|
||||||
while (i != endi && j != gatherers.end()) {
|
while (i != endi && j != gatherers.end()) {
|
||||||
const QString vi = *i;
|
const QString vi = *i;
|
||||||
QString vj = j.value()->fullName();
|
QString vj = j.value()->fullName();
|
||||||
@@ -1253,6 +1336,7 @@ void ServiceBrowserPrivate::maybeUpdateLists()
|
|||||||
pendingGatherers.removeAll(j.value());
|
pendingGatherers.removeAll(j.value());
|
||||||
j.value()->retireService();
|
j.value()->retireService();
|
||||||
j = gatherers.erase(j);
|
j = gatherers.erase(j);
|
||||||
|
hasServicesChanges = true;
|
||||||
} else {
|
} else {
|
||||||
++j;
|
++j;
|
||||||
}
|
}
|
||||||
@@ -1266,17 +1350,20 @@ void ServiceBrowserPrivate::maybeUpdateLists()
|
|||||||
pendingGatherers.removeAll(j.value());
|
pendingGatherers.removeAll(j.value());
|
||||||
j.value()->retireService();
|
j.value()->retireService();
|
||||||
j = gatherers.erase(j);
|
j = gatherers.erase(j);
|
||||||
|
hasServicesChanges = true;
|
||||||
} else {
|
} else {
|
||||||
++j;
|
++j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (const ServiceGatherer::Ptr &g, pendingGatherers)
|
foreach (const ServiceGatherer::Ptr &g, pendingGatherers)
|
||||||
g->enactServiceChange();
|
hasServicesChanges = hasServicesChanges || g->enactServiceChange();
|
||||||
{
|
if (hasServicesChanges) {
|
||||||
QMutexLocker l(mainConnection->lock());
|
{
|
||||||
activeServices = nextActiveServices;
|
QMutexLocker l(mainConnection->lock());
|
||||||
|
activeServices = nextActiveServices;
|
||||||
|
}
|
||||||
|
emit q->servicesUpdated(q);
|
||||||
}
|
}
|
||||||
emit q->servicesUpdated(q);
|
|
||||||
}
|
}
|
||||||
if (shouldRefresh)
|
if (shouldRefresh)
|
||||||
refresh();
|
refresh();
|
||||||
@@ -1333,6 +1420,11 @@ void ServiceBrowserPrivate::browseReply(DNSServiceFlags flag
|
|||||||
maybeUpdateLists(); // avoid?
|
maybeUpdateLists(); // avoid?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServiceBrowserPrivate::activateAutoRefresh()
|
||||||
|
{
|
||||||
|
emit q->activateAutoRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
void ServiceBrowserPrivate::startBrowsing(quint32 interfaceIndex)
|
void ServiceBrowserPrivate::startBrowsing(quint32 interfaceIndex)
|
||||||
{
|
{
|
||||||
this->interfaceIndex = interfaceIndex;
|
this->interfaceIndex = interfaceIndex;
|
||||||
@@ -1364,11 +1456,18 @@ bool ServiceBrowserPrivate::internalStartBrowsing()
|
|||||||
|
|
||||||
void ServiceBrowserPrivate::triggerRefresh()
|
void ServiceBrowserPrivate::triggerRefresh()
|
||||||
{
|
{
|
||||||
QMutexLocker l(mainConnection->lock());
|
{
|
||||||
const qint64 msecDelay = 5100;
|
QMutexLocker l(mainConnection->lock());
|
||||||
delayDeletesUntil = QDateTime::currentMSecsSinceEpoch() + msecDelay;
|
const qint64 msecDelay = 5100;
|
||||||
stopBrowsing();
|
delayDeletesUntil = QDateTime::currentMSecsSinceEpoch() + msecDelay;
|
||||||
shouldRefresh = true;
|
stopBrowsing();
|
||||||
|
shouldRefresh = true;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
QMutexLocker l(mainConnection->mainThreadLock());
|
||||||
|
if (!browsing)
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceBrowserPrivate::refresh()
|
void ServiceBrowserPrivate::refresh()
|
||||||
@@ -1444,6 +1543,11 @@ void ServiceBrowserPrivate::hadFailure(const QList<ErrorMessage> &messages)
|
|||||||
emit q->hadFailure(messages, q);
|
emit q->hadFailure(messages, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServiceBrowserPrivate::startedBrowsing()
|
||||||
|
{
|
||||||
|
emit q->startedBrowsing(q);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------- MainConnection impl -----------------
|
// ----------------- MainConnection impl -----------------
|
||||||
|
|
||||||
void MainConnection::stop(bool wait)
|
void MainConnection::stop(bool wait)
|
||||||
@@ -1463,8 +1567,8 @@ void MainConnection::stop(bool wait)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MainConnection::MainConnection():
|
MainConnection::MainConnection():
|
||||||
lib(zeroConfLibInstance()->defaultLib()), m_lock(QMutex::Recursive), m_mainRef(0),
|
lib(zeroConfLibInstance()->defaultLib()), m_lock(QMutex::Recursive),
|
||||||
m_failed(false), m_status(Starting), m_nErrs(0)
|
m_mainThreadLock(QMutex::Recursive), m_mainRef(0), m_failed(false), m_status(Starting), m_nErrs(0)
|
||||||
{
|
{
|
||||||
if (lib.isNull()){
|
if (lib.isNull()){
|
||||||
qDebug() << "could not load a valid library for ZeroConf::MainConnection, failing";
|
qDebug() << "could not load a valid library for ZeroConf::MainConnection, failing";
|
||||||
@@ -1505,6 +1609,11 @@ QMutex *MainConnection::lock()
|
|||||||
return &m_lock;
|
return &m_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMutex *MainConnection::mainThreadLock()
|
||||||
|
{
|
||||||
|
return &m_mainThreadLock;
|
||||||
|
}
|
||||||
|
|
||||||
void MainConnection::waitStartup()
|
void MainConnection::waitStartup()
|
||||||
{
|
{
|
||||||
int sAtt;
|
int sAtt;
|
||||||
@@ -1537,9 +1646,8 @@ void MainConnection::addBrowser(ServiceBrowserPrivate *browser)
|
|||||||
m_browsers.append(browser);
|
m_browsers.append(browser);
|
||||||
errs = m_errors;
|
errs = m_errors;
|
||||||
}
|
}
|
||||||
if (actualStatus == Running) {
|
if (actualStatus == Running && browser->internalStartBrowsing())
|
||||||
browser->internalStartBrowsing();
|
browser->startedBrowsing();
|
||||||
}
|
|
||||||
bool didFail = false;
|
bool didFail = false;
|
||||||
foreach (const ErrorMessage &msg, errs) {
|
foreach (const ErrorMessage &msg, errs) {
|
||||||
browser->errorMessage(msg.severity, msg.msg);
|
browser->errorMessage(msg.severity, msg.msg);
|
||||||
@@ -1620,7 +1728,7 @@ void MainConnection::createConnection()
|
|||||||
uint32_t size = (uint32_t)sizeof(uint32_t);
|
uint32_t size = (uint32_t)sizeof(uint32_t);
|
||||||
DNSServiceErrorType err = lib->getProperty(kDNSServiceProperty_DaemonVersion, &version, &size);
|
DNSServiceErrorType err = lib->getProperty(kDNSServiceProperty_DaemonVersion, &version, &size);
|
||||||
if (err == kDNSServiceErr_NoError){
|
if (err == kDNSServiceErr_NoError){
|
||||||
DNSServiceErrorType error = lib->createConnection(&m_mainRef);
|
DNSServiceErrorType error = lib->createConnection(this, &m_mainRef);
|
||||||
if (error != kDNSServiceErr_NoError){
|
if (error != kDNSServiceErr_NoError){
|
||||||
appendError(ErrorMessage::WarningLevel, tr("MainConnection using lib %1 failed the initialization of mainRef with error %2")
|
appendError(ErrorMessage::WarningLevel, tr("MainConnection using lib %1 failed the initialization of mainRef with error %2")
|
||||||
.arg(lib->name()).arg(error));
|
.arg(lib->name()).arg(error));
|
||||||
@@ -1636,8 +1744,9 @@ void MainConnection::createConnection()
|
|||||||
}
|
}
|
||||||
for (int i = waitingBrowsers.count(); i-- != 0; ){
|
for (int i = waitingBrowsers.count(); i-- != 0; ){
|
||||||
ServiceBrowserPrivate *actualBrowser = waitingBrowsers[i];
|
ServiceBrowserPrivate *actualBrowser = waitingBrowsers[i];
|
||||||
if (actualBrowser && !actualBrowser->browsing)
|
if (actualBrowser && !actualBrowser->browsing
|
||||||
actualBrowser->internalStartBrowsing();
|
&& actualBrowser->internalStartBrowsing())
|
||||||
|
actualBrowser->startedBrowsing();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1672,11 +1781,11 @@ ZConfLib::RunLoopStatus MainConnection::handleEvent()
|
|||||||
nextEvent = bAtt->delayDeletesUntil;
|
nextEvent = bAtt->delayDeletesUntil;
|
||||||
}
|
}
|
||||||
if (nextEvent <= now)
|
if (nextEvent <= now)
|
||||||
nextEvent = 5000;
|
nextEvent = -1;
|
||||||
else
|
else
|
||||||
nextEvent -= now;
|
nextEvent -= now;
|
||||||
maybeUpdateLists();
|
maybeUpdateLists();
|
||||||
ZConfLib::RunLoopStatus err = lib->processOneEvent(m_mainRef, nextEvent);
|
ZConfLib::RunLoopStatus err = lib->processOneEvent(this, m_mainRef, nextEvent);
|
||||||
if (err != ZConfLib::ProcessedOk && err != ZConfLib::ProcessedIdle) {
|
if (err != ZConfLib::ProcessedOk && err != ZConfLib::ProcessedIdle) {
|
||||||
qDebug() << "processOneEvent returned " << err;
|
qDebug() << "processOneEvent returned " << err;
|
||||||
++m_nErrs;
|
++m_nErrs;
|
||||||
@@ -1715,6 +1824,7 @@ void MainConnection::handleEvents()
|
|||||||
#else
|
#else
|
||||||
while (m_status < Stopping) {
|
while (m_status < Stopping) {
|
||||||
#endif
|
#endif
|
||||||
|
QMutexLocker l(mainThreadLock());
|
||||||
if (m_nErrs > 10)
|
if (m_nErrs > 10)
|
||||||
increaseStatusTo(Stopping);
|
increaseStatusTo(Stopping);
|
||||||
switch (handleEvent()) {
|
switch (handleEvent()) {
|
||||||
@@ -1821,45 +1931,50 @@ void ZConfLib::setError(bool failure, const QString &eMsg)
|
|||||||
m_isOk = !failure;
|
m_isOk = !failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZConfLib::RunLoopStatus ZConfLib::processOneEvent(ConnectionRef cRef, qint64 maxMsBlock)
|
ZConfLib::RunLoopStatus ZConfLib::processOneEvent(MainConnection *mainConnection,
|
||||||
|
ConnectionRef cRef, qint64 maxMsBlock)
|
||||||
{
|
{
|
||||||
if (maxMsBlock < 0) { // just block
|
if (maxMsBlock < 0) { // just block
|
||||||
return processOneEventBlock(cRef);
|
maxMsBlock = MAX_SEC_FOR_READ * static_cast<qint64>(1000);
|
||||||
} else {
|
|
||||||
// some stuff could be extracted for maximal performance
|
|
||||||
int dns_sd_fd = (cRef ? refSockFD(cRef) : -1);
|
|
||||||
int nfds = dns_sd_fd + 1;
|
|
||||||
fd_set readfds;
|
|
||||||
struct timeval tv;
|
|
||||||
int result;
|
|
||||||
dns_sd_fd = (cRef ? refSockFD(cRef) : -1);
|
|
||||||
if (dns_sd_fd < 0)
|
|
||||||
return ProcessedError;
|
|
||||||
nfds = dns_sd_fd + 1;
|
|
||||||
FD_ZERO(&readfds);
|
|
||||||
FD_SET(dns_sd_fd, &readfds);
|
|
||||||
|
|
||||||
if (maxMsBlock > MAX_SEC_FOR_READ * static_cast<qint64>(1000)) {
|
|
||||||
tv.tv_sec = MAX_SEC_FOR_READ;
|
|
||||||
tv.tv_usec = 0;
|
|
||||||
} else {
|
|
||||||
tv.tv_sec = static_cast<time_t>(maxMsBlock / 1000);
|
|
||||||
tv.tv_usec = static_cast<suseconds_t>((maxMsBlock % 1000) * 1000);
|
|
||||||
}
|
|
||||||
result = select(nfds, &readfds, (fd_set *)NULL, (fd_set *)NULL, &tv);
|
|
||||||
if (result > 0) {
|
|
||||||
if (FD_ISSET(dns_sd_fd, &readfds))
|
|
||||||
return processOneEventBlock(cRef);
|
|
||||||
} else if (result == 0) {
|
|
||||||
return ProcessedIdle;
|
|
||||||
} else if (errno != EINTR) {
|
|
||||||
if (DEBUG_ZEROCONF)
|
|
||||||
qDebug() << "select() returned " << result << " errno " << errno
|
|
||||||
<< strerror(errno);
|
|
||||||
return ProcessedError;
|
|
||||||
}
|
|
||||||
return ProcessedIdle; // change? should never happen anyway
|
|
||||||
}
|
}
|
||||||
|
// some stuff could be extracted for maximal performance
|
||||||
|
int dns_sd_fd = (cRef ? refSockFD(cRef) : -1);
|
||||||
|
int nfds = dns_sd_fd + 1;
|
||||||
|
fd_set readfds;
|
||||||
|
struct timeval tv;
|
||||||
|
int result;
|
||||||
|
dns_sd_fd = (cRef ? refSockFD(cRef) : -1);
|
||||||
|
if (dns_sd_fd < 0)
|
||||||
|
return ProcessedError;
|
||||||
|
nfds = dns_sd_fd + 1;
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(dns_sd_fd, &readfds);
|
||||||
|
|
||||||
|
if (maxMsBlock > MAX_SEC_FOR_READ * static_cast<qint64>(1000)) {
|
||||||
|
tv.tv_sec = MAX_SEC_FOR_READ;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
} else {
|
||||||
|
tv.tv_sec = static_cast<time_t>(maxMsBlock / 1000);
|
||||||
|
tv.tv_usec = static_cast<suseconds_t>((maxMsBlock % 1000) * 1000);
|
||||||
|
}
|
||||||
|
QMutex *lock = (mainConnection ? mainConnection->mainThreadLock() : 0);
|
||||||
|
if (lock)
|
||||||
|
lock->unlock();
|
||||||
|
result = select(nfds, &readfds, (fd_set *)NULL, (fd_set *)NULL, &tv);
|
||||||
|
if (lock)
|
||||||
|
lock->lock();
|
||||||
|
if (result > 0) {
|
||||||
|
if (FD_ISSET(dns_sd_fd, &readfds))
|
||||||
|
return processOneEventBlock(cRef);
|
||||||
|
} else if (result == 0) {
|
||||||
|
return ProcessedIdle;
|
||||||
|
} else if (errno != EINTR) {
|
||||||
|
if (DEBUG_ZEROCONF)
|
||||||
|
qDebug() << "select() returned " << result << " errno " << errno
|
||||||
|
<< strerror(errno);
|
||||||
|
return ProcessedError;
|
||||||
|
}
|
||||||
|
return ProcessedIdle; // change? should never happen anyway
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -39,6 +39,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QHostInfo)
|
QT_FORWARD_DECLARE_CLASS(QHostInfo)
|
||||||
|
|
||||||
@@ -99,6 +100,7 @@ public:
|
|||||||
const ServiceTxtRecord &txtRecord() const { return m_txtRecord; }
|
const ServiceTxtRecord &txtRecord() const { return m_txtRecord; }
|
||||||
const QHostInfo *host() const { return m_host; }
|
const QHostInfo *host() const { return m_host; }
|
||||||
int interfaceNr() const { return m_interfaceNr; }
|
int interfaceNr() const { return m_interfaceNr; }
|
||||||
|
bool operator==(const Service &o) const;
|
||||||
|
|
||||||
bool invalidate() { bool res = m_outdated; m_outdated = true; return res; }
|
bool invalidate() { bool res = m_outdated; m_outdated = true; return res; }
|
||||||
private:
|
private:
|
||||||
@@ -114,6 +116,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
ZEROCONFSHARED_EXPORT QDebug operator<<(QDebug dbg, const Service &service);
|
ZEROCONFSHARED_EXPORT QDebug operator<<(QDebug dbg, const Service &service);
|
||||||
|
ZEROCONFSHARED_EXPORT QDebug operator<<(QDebug dbg, const Service::ConstPtr &service);
|
||||||
|
|
||||||
class ZEROCONFSHARED_EXPORT ServiceBrowser : public QObject
|
class ZEROCONFSHARED_EXPORT ServiceBrowser : public QObject
|
||||||
{
|
{
|
||||||
@@ -133,7 +136,6 @@ public:
|
|||||||
|
|
||||||
void startBrowsing(qint32 interfaceIndex = 0);
|
void startBrowsing(qint32 interfaceIndex = 0);
|
||||||
void stopBrowsing();
|
void stopBrowsing();
|
||||||
void triggerRefresh();
|
|
||||||
bool isBrowsing() const;
|
bool isBrowsing() const;
|
||||||
bool didFail() const;
|
bool didFail() const;
|
||||||
|
|
||||||
@@ -145,7 +147,11 @@ public:
|
|||||||
|
|
||||||
QList<Service::ConstPtr> services() const;
|
QList<Service::ConstPtr> services() const;
|
||||||
void reconfirmService(Service::ConstPtr service);
|
void reconfirmService(Service::ConstPtr service);
|
||||||
|
public slots:
|
||||||
|
void triggerRefresh();
|
||||||
|
void autoRefresh();
|
||||||
signals:
|
signals:
|
||||||
|
void activateAutoRefresh();
|
||||||
void serviceChanged(const ZeroConf::Service::ConstPtr &oldService,
|
void serviceChanged(const ZeroConf::Service::ConstPtr &oldService,
|
||||||
const ZeroConf::Service::ConstPtr &newService, ZeroConf::ServiceBrowser *browser);
|
const ZeroConf::Service::ConstPtr &newService, ZeroConf::ServiceBrowser *browser);
|
||||||
void serviceAdded(const ZeroConf::Service::ConstPtr &service,
|
void serviceAdded(const ZeroConf::Service::ConstPtr &service,
|
||||||
@@ -155,7 +161,9 @@ signals:
|
|||||||
void servicesUpdated(ZeroConf::ServiceBrowser *browser);
|
void servicesUpdated(ZeroConf::ServiceBrowser *browser);
|
||||||
void errorMessage(ZeroConf::ErrorMessage::SeverityLevel severity, const QString &msg, ZeroConf::ServiceBrowser *browser);
|
void errorMessage(ZeroConf::ErrorMessage::SeverityLevel severity, const QString &msg, ZeroConf::ServiceBrowser *browser);
|
||||||
void hadFailure(const QList<ZeroConf::ErrorMessage> &messages, ZeroConf::ServiceBrowser *browser);
|
void hadFailure(const QList<ZeroConf::ErrorMessage> &messages, ZeroConf::ServiceBrowser *browser);
|
||||||
|
void startedBrowsing(ZeroConf::ServiceBrowser *browser);
|
||||||
private:
|
private:
|
||||||
|
QTimer *timer;
|
||||||
Internal::ServiceBrowserPrivate *d;
|
Internal::ServiceBrowserPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -109,8 +109,10 @@ public:
|
|||||||
ServiceBrowserPrivate *browser) = 0;
|
ServiceBrowserPrivate *browser) = 0;
|
||||||
virtual DNSServiceErrorType getProperty(const char *property, void *result, uint32_t *size) = 0;
|
virtual DNSServiceErrorType getProperty(const char *property, void *result, uint32_t *size) = 0;
|
||||||
virtual RunLoopStatus processOneEventBlock(ConnectionRef sdRef) = 0;
|
virtual RunLoopStatus processOneEventBlock(ConnectionRef sdRef) = 0;
|
||||||
virtual RunLoopStatus processOneEvent(ConnectionRef sdRef, qint64 maxMsBlock);
|
virtual RunLoopStatus processOneEvent(MainConnection *mainConnection,
|
||||||
virtual DNSServiceErrorType createConnection(ConnectionRef *sdRef) = 0;
|
ConnectionRef sdRef, qint64 maxMsBlock);
|
||||||
|
virtual DNSServiceErrorType createConnection(MainConnection *mainConnection,
|
||||||
|
ConnectionRef *sdRef) = 0;
|
||||||
virtual void stopConnection(ConnectionRef cRef) = 0;
|
virtual void stopConnection(ConnectionRef cRef) = 0;
|
||||||
virtual void destroyConnection(ConnectionRef *sdRef) = 0;
|
virtual void destroyConnection(ConnectionRef *sdRef) = 0;
|
||||||
virtual int refSockFD(ConnectionRef sdRef) = 0;
|
virtual int refSockFD(ConnectionRef sdRef) = 0;
|
||||||
@@ -154,7 +156,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
QString fullName();
|
QString fullName();
|
||||||
void enactServiceChange();
|
bool enactServiceChange();
|
||||||
void retireService();
|
void retireService();
|
||||||
Ptr gatherer();
|
Ptr gatherer();
|
||||||
|
|
||||||
@@ -232,6 +234,7 @@ public:
|
|||||||
MainConnection();
|
MainConnection();
|
||||||
~MainConnection();
|
~MainConnection();
|
||||||
QMutex *lock();
|
QMutex *lock();
|
||||||
|
QMutex *mainThreadLock();
|
||||||
void waitStartup();
|
void waitStartup();
|
||||||
void stop(bool wait = true);
|
void stop(bool wait = true);
|
||||||
void addBrowser(ServiceBrowserPrivate *browser);
|
void addBrowser(ServiceBrowserPrivate *browser);
|
||||||
@@ -253,7 +256,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void appendError(ErrorMessage::SeverityLevel severity, const QString &msg);
|
void appendError(ErrorMessage::SeverityLevel severity, const QString &msg);
|
||||||
|
|
||||||
mutable QMutex m_lock;
|
mutable QMutex m_lock, m_mainThreadLock;
|
||||||
QList<ServiceBrowserPrivate *> m_browsers;
|
QList<ServiceBrowserPrivate *> m_browsers;
|
||||||
ZConfLib::ConnectionRef m_mainRef;
|
ZConfLib::ConnectionRef m_mainRef;
|
||||||
bool m_failed;
|
bool m_failed;
|
||||||
@@ -309,6 +312,7 @@ public:
|
|||||||
uint32_t interfaceIndex, ZK_IP_Protocol proto, DNSServiceErrorType errorCode,
|
uint32_t interfaceIndex, ZK_IP_Protocol proto, DNSServiceErrorType errorCode,
|
||||||
const char *serviceName, const char *regtype, const char *replyDomain);
|
const char *serviceName, const char *regtype, const char *replyDomain);
|
||||||
|
|
||||||
|
void activateAutoRefresh();
|
||||||
void serviceChanged(const Service::ConstPtr &oldService, const Service::ConstPtr &newService,
|
void serviceChanged(const Service::ConstPtr &oldService, const Service::ConstPtr &newService,
|
||||||
ServiceBrowser *browser);
|
ServiceBrowser *browser);
|
||||||
void serviceAdded(const Service::ConstPtr &service, ServiceBrowser *browser);
|
void serviceAdded(const Service::ConstPtr &service, ServiceBrowser *browser);
|
||||||
@@ -316,6 +320,7 @@ public:
|
|||||||
void servicesUpdated(ServiceBrowser *browser);
|
void servicesUpdated(ServiceBrowser *browser);
|
||||||
void errorMessage(ErrorMessage::SeverityLevel severity, const QString &msg);
|
void errorMessage(ErrorMessage::SeverityLevel severity, const QString &msg);
|
||||||
void hadFailure(const QList<ErrorMessage> &msgs);
|
void hadFailure(const QList<ErrorMessage> &msgs);
|
||||||
|
void startedBrowsing();
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConnectionThread: public QThread {
|
class ConnectionThread: public QThread {
|
||||||
|
Reference in New Issue
Block a user