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:
Fawzi Mohamed
2012-03-08 20:06:52 +01:00
parent f1b2100e34
commit a9e7e07b45
10 changed files with 6451 additions and 88 deletions

View File

@@ -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

View File

@@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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);
} }

View File

@@ -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));
} }

View File

@@ -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

View File

@@ -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;
}; };

View File

@@ -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 {