Bonjour support.

This commit is contained in:
Stefan Hacker 2009-06-10 20:32:32 +02:00
parent 19fde80b7d
commit 6582af7d3c
23 changed files with 1351 additions and 331 deletions

View File

@ -89,6 +89,12 @@ users=100
#registerUrl=http://mumble.sourceforge.net/
#registerHostname=
# To enable bonjour service discovery uncomment the following line.
# To change the name announced by bonjour adjust the registerName variable.
# See http://developer.apple.com/networking/bonjour/index.html for more information
# about bonjour.
#bonjour=True
# If you have a proper SSL certificate, you can provide the filenames here.
#sslCert=
#sslKey=

View File

@ -0,0 +1,60 @@
/*
Copyright (c) 2007, Trenton Schulz
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BONJOURRECORD_H
#define BONJOURRECORD_H
#include <QtCore/QMetaType>
#include <QtCore/QString>
class BonjourRecord
{
public:
BonjourRecord() {}
BonjourRecord(const QString &name, const QString &regType, const QString &domain)
: serviceName(name), registeredType(regType), replyDomain(domain)
{}
BonjourRecord(const char *name, const char *regType, const char *domain)
{
serviceName = QString::fromUtf8(name);
registeredType = QString::fromUtf8(regType);
replyDomain = QString::fromUtf8(domain);
}
QString serviceName;
QString registeredType;
QString replyDomain;
bool operator==(const BonjourRecord &other) const {
return serviceName == other.serviceName
&& registeredType == other.registeredType
&& replyDomain == other.replyDomain;
}
};
Q_DECLARE_METATYPE(BonjourRecord)
#endif // BONJOURRECORD_H

View File

@ -0,0 +1,90 @@
/*
Copyright (c) 2007, Trenton Schulz
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "bonjourservicebrowser.h"
#include <QtCore/QSocketNotifier>
BonjourServiceBrowser::BonjourServiceBrowser(QObject *parent)
: QObject(parent), dnssref(0), bonjourSocket(0)
{
}
BonjourServiceBrowser::~BonjourServiceBrowser()
{
if (dnssref) {
DNSServiceRefDeallocate(dnssref);
dnssref = 0;
}
}
void BonjourServiceBrowser::browseForServiceType(const QString &serviceType)
{
DNSServiceErrorType err = DNSServiceBrowse(&dnssref, 0, 0, serviceType.toUtf8().constData(), 0,
bonjourBrowseReply, this);
if (err != kDNSServiceErr_NoError) {
emit error(err);
} else {
int sockfd = DNSServiceRefSockFD(dnssref);
if (sockfd == -1) {
emit error(kDNSServiceErr_Invalid);
} else {
bonjourSocket = new QSocketNotifier(sockfd, QSocketNotifier::Read, this);
connect(bonjourSocket, SIGNAL(activated(int)), this, SLOT(bonjourSocketReadyRead()));
}
}
}
void BonjourServiceBrowser::bonjourSocketReadyRead()
{
DNSServiceErrorType err = DNSServiceProcessResult(dnssref);
if (err != kDNSServiceErr_NoError)
emit error(err);
}
void BonjourServiceBrowser::bonjourBrowseReply(DNSServiceRef , DNSServiceFlags flags,
quint32 , DNSServiceErrorType errorCode,
const char *serviceName, const char *regType,
const char *replyDomain, void *context)
{
BonjourServiceBrowser *serviceBrowser = static_cast<BonjourServiceBrowser *>(context);
if (errorCode != kDNSServiceErr_NoError) {
emit serviceBrowser->error(errorCode);
} else {
BonjourRecord bonjourRecord(serviceName, regType, replyDomain);
if (flags & kDNSServiceFlagsAdd) {
if (!serviceBrowser->bonjourRecords.contains(bonjourRecord))
serviceBrowser->bonjourRecords.append(bonjourRecord);
} else {
serviceBrowser->bonjourRecords.removeAll(bonjourRecord);
}
if (!(flags & kDNSServiceFlagsMoreComing)) {
emit serviceBrowser->currentBonjourRecordsChanged(serviceBrowser->bonjourRecords);
}
}
}

View File

@ -0,0 +1,65 @@
/*
Copyright (c) 2007, Trenton Schulz
Copyright (c) 2009, Stefan Hacker
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BONJOURSERVICEBROWSER_H
#define BONJOURSERVICEBROWSER_H
#include <QtCore/QObject>
#include <dns_sd.h>
#include "bonjourrecord.h"
class QSocketNotifier;
class BonjourServiceBrowser : public QObject
{
Q_OBJECT
public:
BonjourServiceBrowser(QObject *parent = 0);
~BonjourServiceBrowser();
void browseForServiceType(const QString &serviceType);
inline QList<BonjourRecord> currentRecords() const { return bonjourRecords; }
inline QString serviceType() const { return browsingType; }
signals:
void currentBonjourRecordsChanged(const QList<BonjourRecord> &list);
void error(DNSServiceErrorType err);
private slots:
void bonjourSocketReadyRead();
private:
static void DNSSD_API bonjourBrowseReply(DNSServiceRef , DNSServiceFlags flags, quint32,
DNSServiceErrorType errorCode, const char *serviceName,
const char *regType, const char *replyDomain, void *context);
DNSServiceRef dnssref;
QSocketNotifier *bonjourSocket;
QList<BonjourRecord> bonjourRecords;
QString browsingType;
};
#endif // BONJOURSERVICEBROWSER_H

View File

@ -0,0 +1,100 @@
/*
Copyright (c) 2007, Trenton Schulz
Copyright (c) 2009, Stefan Hacker
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "bonjourserviceregister.h"
#include <QtCore/QSocketNotifier>
BonjourServiceRegister::BonjourServiceRegister(QObject *parent)
: QObject(parent), dnssref(0), bonjourSocket(0)
{
}
BonjourServiceRegister::~BonjourServiceRegister()
{
if (dnssref) {
DNSServiceRefDeallocate(dnssref);
dnssref = 0;
}
}
void BonjourServiceRegister::registerService(const BonjourRecord &record, quint16 servicePort)
{
if (dnssref) {
qWarning("Warning: Already registered a service for this object, aborting new register");
return;
}
quint16 bigEndianPort = servicePort;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
{
bigEndianPort = 0 | ((servicePort & 0x00ff) << 8) | ((servicePort & 0xff00) >> 8);
}
#endif
DNSServiceErrorType err = DNSServiceRegister(&dnssref, 0, 0, record.serviceName.toUtf8().constData(),
record.registeredType.toUtf8().constData(),
record.replyDomain.isEmpty() ? 0
: record.replyDomain.toUtf8().constData(), 0,
bigEndianPort, 0, 0, bonjourRegisterService, this);
if (err != kDNSServiceErr_NoError) {
emit error(err);
} else {
int sockfd = DNSServiceRefSockFD(dnssref);
if (sockfd == -1) {
emit error(kDNSServiceErr_Invalid);
} else {
bonjourSocket = new QSocketNotifier(sockfd, QSocketNotifier::Read, this);
connect(bonjourSocket, SIGNAL(activated(int)), this, SLOT(bonjourSocketReadyRead()));
}
}
}
void BonjourServiceRegister::bonjourSocketReadyRead()
{
DNSServiceErrorType err = DNSServiceProcessResult(dnssref);
if (err != kDNSServiceErr_NoError)
emit error(err);
}
void DNSSD_API BonjourServiceRegister::bonjourRegisterService(DNSServiceRef, DNSServiceFlags,
DNSServiceErrorType errorCode, const char *name,
const char *regtype, const char *domain,
void *data)
{
BonjourServiceRegister *serviceRegister = static_cast<BonjourServiceRegister *>(data);
if (errorCode != kDNSServiceErr_NoError) {
emit serviceRegister->error(errorCode);
} else {
serviceRegister->finalRecord = BonjourRecord(QString::fromUtf8(name),
QString::fromUtf8(regtype),
QString::fromUtf8(domain));
emit serviceRegister->serviceRegistered(serviceRegister->finalRecord);
}
}

View File

@ -0,0 +1,72 @@
/*
Copyright (c) 2007, Trenton Schulz
Copyright (c) 2009, Stefan Hacker
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BONJOURSERVICEREGISTER_H
#define BONJOURSERVICEREGISTER_H
#include <QtCore/QObject>
#include "bonjourrecord.h"
class QSocketNotifier;
// Bonjour flags
#include <dns_sd.h>
typedef uint32_t DNSServiceFlags;
typedef int32_t DNSServiceErrorType;
typedef struct _DNSServiceRef_t *DNSServiceRef;
class BonjourServiceRegister : public QObject
{
Q_OBJECT
public:
BonjourServiceRegister(QObject *parent = 0);
~BonjourServiceRegister();
void registerService(const BonjourRecord &record, quint16 servicePort);
inline BonjourRecord registeredRecord() const {return finalRecord; }
signals:
void error(DNSServiceErrorType error);
void serviceRegistered(const BonjourRecord &record);
private slots:
void bonjourSocketReadyRead();
private:
static void DNSSD_API bonjourRegisterService(DNSServiceRef sdRef, DNSServiceFlags,
DNSServiceErrorType errorCode, const char *name,
const char *regtype, const char *domain,
void *context);
DNSServiceRef dnssref;
QSocketNotifier *bonjourSocket;
BonjourRecord finalRecord;
};
#endif // BONJOURSERVICEREGISTER_H

View File

@ -0,0 +1,111 @@
/*
Copyright (c) 2007, Trenton Schulz
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <QtCore/QSocketNotifier>
#include <QtNetwork/QHostInfo>
#include "bonjourrecord.h"
#include "bonjourserviceresolver.h"
BonjourServiceResolver::BonjourServiceResolver(QObject *parent)
: QObject(parent), dnssref(0), bonjourSocket(0), bonjourPort(-1)
{
}
BonjourServiceResolver::~BonjourServiceResolver()
{
cleanupResolve();
}
void BonjourServiceResolver::cleanupResolve()
{
if (dnssref) {
DNSServiceRefDeallocate(dnssref);
dnssref = 0;
delete bonjourSocket;
bonjourPort = -1;
}
}
void BonjourServiceResolver::resolveBonjourRecord(const BonjourRecord &record)
{
if (dnssref) {
qWarning("resolve in process, aborting");
return;
}
DNSServiceErrorType err = DNSServiceResolve(&dnssref, 0, 0,
record.serviceName.toUtf8().constData(),
record.registeredType.toUtf8().constData(),
record.replyDomain.toUtf8().constData(),
(DNSServiceResolveReply)bonjourResolveReply, this);
if (err != kDNSServiceErr_NoError) {
emit error(err);
} else {
int sockfd = DNSServiceRefSockFD(dnssref);
if (sockfd == -1) {
emit error(kDNSServiceErr_Invalid);
} else {
bonjourSocket = new QSocketNotifier(sockfd, QSocketNotifier::Read, this);
connect(bonjourSocket, SIGNAL(activated(int)), this, SLOT(bonjourSocketReadyRead()));
}
}
}
void BonjourServiceResolver::bonjourSocketReadyRead()
{
DNSServiceErrorType err = DNSServiceProcessResult(dnssref);
if (err != kDNSServiceErr_NoError)
emit error(err);
}
void BonjourServiceResolver::bonjourResolveReply(DNSServiceRef, DNSServiceFlags ,
quint32 , DNSServiceErrorType errorCode,
const char *, const char *hosttarget, quint16 port,
quint16 , const char *, void *context)
{
BonjourServiceResolver *serviceResolver = static_cast<BonjourServiceResolver *>(context);
if (errorCode != kDNSServiceErr_NoError) {
emit serviceResolver->error(errorCode);
return;
}
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
{
port = 0 | ((port & 0x00ff) << 8) | ((port & 0xff00) >> 8);
}
#endif
serviceResolver->bonjourPort = port;
QHostInfo::lookupHost(QString::fromUtf8(hosttarget),
serviceResolver, SLOT(finishConnect(const QHostInfo &)));
}
void BonjourServiceResolver::finishConnect(const QHostInfo &hostInfo)
{
emit bonjourRecordResolved(hostInfo, bonjourPort);
QMetaObject::invokeMethod(this, "cleanupResolve", Qt::QueuedConnection);
}

View File

@ -0,0 +1,68 @@
/*
Copyright (c) 2007, Trenton Schulz
Copyright (c) 2009, Stefan Hacker
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BONJOURSERVICERESOLVER_H
#define BONJOURSERVICERESOLVER_H
#include <QtCore/QObject>
#include <dns_sd.h>
class QSocketNotifier;
class QHostInfo;
class BonjourRecord;
class BonjourServiceResolver : public QObject
{
Q_OBJECT
public:
BonjourServiceResolver(QObject *parent);
~BonjourServiceResolver();
void resolveBonjourRecord(const BonjourRecord &record);
signals:
void bonjourRecordResolved(const QHostInfo &hostInfo, int port);
void error(DNSServiceErrorType error);
private slots:
void bonjourSocketReadyRead();
void cleanupResolve();
void finishConnect(const QHostInfo &hostInfo);
private:
static void DNSSD_API bonjourResolveReply(DNSServiceRef sdRef, DNSServiceFlags flags,
quint32 interfaceIndex, DNSServiceErrorType errorCode,
const char *fullName, const char *hosttarget, quint16 port,
quint16 txtLen, const char *txtRecord, void *context);
DNSServiceRef dnssref;
QSocketNotifier *bonjourSocket;
int bonjourPort;
};
#endif // BONJOURSERVICERESOLVER_H

View File

@ -0,0 +1,51 @@
/* Copyright (C) 2009, Stefan Hacker
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "BonjourClient.h"
BonjourClient::BonjourClient() : bsrResolver(NULL), bsbBrowser(NULL) {
HMODULE hLib = LoadLibrary(L"DNSSD.DLL");
if (hLib == NULL) {
qWarning("Bonjour: Failed to load dnssd.dll");
return;
}
FreeLibrary(hLib);
bsbBrowser = new BonjourServiceBrowser(this);
bsbBrowser->browseForServiceType(QLatin1String("_murmur._tcp"));
bsrResolver = new BonjourServiceResolver(this);
return;
}
BonjourClient::~BonjourClient() {
if (bsbBrowser)
delete bsbBrowser;
if (bsrResolver)
delete bsrResolver;
}

View File

@ -0,0 +1,52 @@
/* Copyright (C) 2009, Stefan Hacker
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _BONJOURCLIENT_H
#define _BONJOURCLIENT_H
#include <delayimp.h>
#include "../Bonjour/bonjourservicebrowser.h"
#include "../Bonjour/bonjourserviceresolver.h"
class BonjourClient : public QObject {
private:
Q_OBJECT
Q_DISABLE_COPY(BonjourClient)
public:
BonjourClient();
~BonjourClient();
BonjourServiceBrowser *bsbBrowser;
BonjourServiceResolver *bsrResolver;
};
#else
class Bonjour;
class BonjourServer;
#endif

View File

@ -58,7 +58,6 @@ ConnectDialog::ConnectDialog(QWidget *p) : QDialog(p) {
#ifdef Q_OS_MAC
setWindowFlags(Qt::Sheet);
#endif
bPublicInit = false;
bDirty = false;
@ -86,6 +85,9 @@ ConnectDialog::ConnectDialog(QWidget *p) : QDialog(p) {
connect(qleServer, SIGNAL(textEdited(const QString &)), this, SLOT(onDirty(const QString &)));
connect(qleUsername, SIGNAL(textEdited(const QString &)), this, SLOT(onDirty(const QString &)));
connect(qlePort, SIGNAL(textEdited(const QString &)), this, SLOT(onDirty(const QString &)));
#ifdef USE_BONJOUR
connect(qtwLanServers, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(on_qpbLanBrowserConnect_clicked()));
#endif
qlePort->setValidator(new QIntValidator(1, 65535, qlePort));
@ -101,12 +103,15 @@ ConnectDialog::ConnectDialog(QWidget *p) : QDialog(p) {
}
fillList();
qtwTab->setCurrentIndex(0);
if (qstmServers->rowCount() < 1) {
on_qpbAdd_clicked();
qtwTab->setCurrentIndex(1);
}
if (!initLanList())
qtwTab->removeTab(qtwTab->indexOf(qwTabLan));
qtwTab->setCurrentIndex(0);
}
void ConnectDialog::accept() {
@ -173,6 +178,80 @@ void ConnectDialog::initList() {
connect(rep, SIGNAL(finished()), this, SLOT(finished()));
}
bool ConnectDialog::initLanList() {
#ifdef USE_BONJOUR
// Make sure the we got the objects we need, then wire them up
if (g.bc->bsbBrowser == NULL || g.bc->bsrResolver == NULL) return false;
connect(g.bc->bsbBrowser, SIGNAL(error(DNSServiceErrorType)),
this, SLOT(onLanBrowseError(DNSServiceErrorType)));
connect(g.bc->bsbBrowser, SIGNAL(currentBonjourRecordsChanged(const QList<BonjourRecord> &)),
this, SLOT(onUpdateLanList(const QList<BonjourRecord> &)));
connect(g.bc->bsrResolver, SIGNAL(error(DNSServiceErrorType)),
this, SLOT(onLanResolveError(DNSServiceErrorType)));
connect(g.bc->bsrResolver, SIGNAL(bonjourRecordResolved(const QHostInfo &, int)),
this, SLOT(accept(const QHostInfo &, int)));
// Manually update list
onUpdateLanList(g.bc->bsbBrowser->currentRecords());
return true;
#else
return false;
#endif
}
#ifdef USE_BONJOUR
void ConnectDialog::accept(const QHostInfo &host, int port) {
if (!bResolving) return;
bResolving = false;
const QList<QHostAddress> &addrs = host.addresses();
if (addrs.isEmpty()) return;
QHostAddress addr(addrs.first());
bool ok;
QString defUserName = QInputDialog::getText(this, tr("Connecting to %1").arg(host.hostName()), tr("Enter username"), QLineEdit::Normal, g.s.qsUsername, &ok).trimmed();
if (! ok)
return;
g.s.qsUsername = defUserName;
qsUsername = defUserName;
qsPassword = QString();
qsServer = addr.toString();
usPort = port;
QDialog::accept();
}
void ConnectDialog::onUpdateLanList(const QList<BonjourRecord> &list) {
qtwLanServers->clear();
foreach (BonjourRecord record, list) {
QVariant hrecord;
hrecord.setValue(record);
QTreeWidgetItem *tmp = new QTreeWidgetItem(qtwLanServers, QStringList() << record.serviceName);
tmp->setData(0, Qt::UserRole, hrecord);
}
}
void ConnectDialog::onLanBrowseError(DNSServiceErrorType err) {
/*DEBUG REMOVE LATER TOFIX TODO*/qWarning()<<"Bonjour reported browser error "<< err;
}
void ConnectDialog::onLanResolveError(DNSServiceErrorType err) {
bResolving = false; // Make sure we don't get stuck due to failed resolving
/*DEBUG REMOVE LATER TOFIX TODO*/qWarning()<<"Bonjour reported resolver error "<< err;
}
void ConnectDialog::on_qpbLanBrowserConnect_clicked() {
QTreeWidgetItem *item = qtwLanServers->currentItem();
if (! item)
return;
QVariant hrecord = item->data(0, Qt::UserRole);
g.bc->bsrResolver->resolveBonjourRecord(hrecord.value<BonjourRecord>());
bResolving = true;
}
#endif
void ConnectDialog::fillList() {
qtwServers->clear();
@ -386,5 +465,6 @@ void ConnectDialog::on_qtwTab_currentChanged(int idx) {
if (idx != 1)
return;
initList();
if (idx == 1)
initList();
}

View File

@ -35,6 +35,10 @@
#include "ui_ConnectDialog.h"
#include "Timer.h"
#ifdef USE_BONJOUR
#include "BonjourClient.h"
#endif
struct PublicInfo {
QString name;
QUrl url;
@ -61,14 +65,24 @@ class ConnectDialog : public QDialog, public Ui::ConnectDialog {
QModelIndex qmiDirty;
QSqlRecord toRecord() const;
bool bDirty;
bool bResolving;
QHttp *qhList;
bool initLanList();
void initList();
void fillList();
void fillEmpty();
public slots:
void accept();
void finished();
#ifdef USE_BONJOUR
void accept(const QHostInfo &, int);
void onUpdateLanList(const QList<BonjourRecord> &);
void onLanBrowseError(DNSServiceErrorType);
void onLanResolveError(DNSServiceErrorType);
void on_qpbLanBrowserConnect_clicked();
#endif
void on_qpbAdd_clicked();
void on_qpbRemove_clicked();
void onSelection_Changed(const QModelIndex &n, const QModelIndex &p);

View File

@ -1,326 +1,388 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConnectDialog</class>
<widget class="QDialog" name="ConnectDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>505</width>
<height>296</height>
</rect>
</property>
<property name="windowTitle">
<string>Mumble Server Connect</string>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QTabWidget" name="qtwTab">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="qwCustom">
<attribute name="title">
<string>&amp;Custom Servers</string>
</attribute>
<layout class="QVBoxLayout">
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QListView" name="qlwServers">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="QLabel" name="qliName">
<property name="text">
<string>&amp;Label</string>
</property>
<property name="buddy">
<cstring>qleName</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="qliServer">
<property name="text">
<string>A&amp;ddress</string>
</property>
<property name="buddy">
<cstring>qleServer</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="qliPort">
<property name="text">
<string>&amp;Port</string>
</property>
<property name="buddy">
<cstring>qlePort</cstring>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="qliUsername">
<property name="text">
<string>&amp;Username</string>
</property>
<property name="buddy">
<cstring>qleUsername</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="qleName"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="qleServer"/>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="qlePort"/>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="qleUsername"/>
</item>
<item row="4" column="0" colspan="2">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QPushButton" name="qpbConnect">
<property name="text">
<string>&amp;Connect</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="qpbCancel">
<property name="text">
<string>&amp;Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="qpbAdd">
<property name="text">
<string>&amp;Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="qpbRemove">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Remove</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="qwPublic">
<attribute name="title">
<string>Server &amp;Browser</string>
</attribute>
<layout class="QVBoxLayout">
<item>
<widget class="QTreeWidget" name="qtwServers">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="itemsExpandable">
<bool>false</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<column>
<property name="text">
<string>Label</string>
</property>
</column>
<column>
<property name="text">
<string>Address</string>
</property>
</column>
<column>
<property name="text">
<string>URL</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QPushButton" name="qpbBrowserConnect">
<property name="text">
<string>&amp;Connect</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="qpbBrowserCancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="qpbCopy">
<property name="text">
<string>C&amp;opy to custom</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="qpbURL">
<property name="text">
<string>&amp;View Webpage</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>qpbConnect</sender>
<signal>clicked()</signal>
<receiver>ConnectDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>21</x>
<y>248</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>541</y>
</hint>
</hints>
</connection>
<connection>
<sender>qpbCancel</sender>
<signal>clicked()</signal>
<receiver>ConnectDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>248</y>
</hint>
<hint type="destinationlabel">
<x>444</x>
<y>541</y>
</hint>
</hints>
</connection>
<connection>
<sender>qlwServers</sender>
<signal>doubleClicked(QModelIndex)</signal>
<receiver>ConnectDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>109</x>
<y>196</y>
</hint>
<hint type="destinationlabel">
<x>133</x>
<y>654</y>
</hint>
</hints>
</connection>
<connection>
<sender>qpbBrowserConnect</sender>
<signal>clicked()</signal>
<receiver>ConnectDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>119</x>
<y>263</y>
</hint>
<hint type="destinationlabel">
<x>117</x>
<y>370</y>
</hint>
</hints>
</connection>
<connection>
<sender>qpbBrowserCancel</sender>
<signal>clicked()</signal>
<receiver>ConnectDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>138</x>
<y>248</y>
</hint>
<hint type="destinationlabel">
<x>20</x>
<y>20</y>
</hint>
</hints>
</connection>
<connection>
<sender>qtwServers</sender>
<signal>doubleClicked(QModelIndex)</signal>
<receiver>ConnectDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>158</x>
<y>128</y>
</hint>
<hint type="destinationlabel">
<x>185</x>
<y>436</y>
</hint>
</hints>
</connection>
</connections>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConnectDialog</class>
<widget class="QDialog" name="ConnectDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>505</width>
<height>296</height>
</rect>
</property>
<property name="windowTitle">
<string>Mumble Server Connect</string>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QTabWidget" name="qtwTab">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="qwCustom">
<attribute name="title">
<string>&amp;Custom Servers</string>
</attribute>
<layout class="QVBoxLayout">
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QListView" name="qlwServers">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="QLabel" name="qliName">
<property name="text">
<string>&amp;Label</string>
</property>
<property name="buddy">
<cstring>qleName</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="qliServer">
<property name="text">
<string>A&amp;ddress</string>
</property>
<property name="buddy">
<cstring>qleServer</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="qliPort">
<property name="text">
<string>&amp;Port</string>
</property>
<property name="buddy">
<cstring>qlePort</cstring>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="qliUsername">
<property name="text">
<string>&amp;Username</string>
</property>
<property name="buddy">
<cstring>qleUsername</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="qleName"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="qleServer"/>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="qlePort"/>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="qleUsername"/>
</item>
<item row="4" column="0" colspan="2">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QPushButton" name="qpbConnect">
<property name="text">
<string>&amp;Connect</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="qpbCancel">
<property name="text">
<string>&amp;Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="qpbAdd">
<property name="text">
<string>&amp;Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="qpbRemove">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Remove</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="qwPublic">
<attribute name="title">
<string>Server &amp;Browser</string>
</attribute>
<layout class="QVBoxLayout">
<item>
<widget class="QTreeWidget" name="qtwServers">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="itemsExpandable">
<bool>false</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<column>
<property name="text">
<string>Label</string>
</property>
</column>
<column>
<property name="text">
<string>Address</string>
</property>
</column>
<column>
<property name="text">
<string>URL</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QPushButton" name="qpbBrowserConnect">
<property name="text">
<string>&amp;Connect</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="qpbBrowserCancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="qpbCopy">
<property name="text">
<string>C&amp;opy to custom</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="qpbURL">
<property name="text">
<string>&amp;View Webpage</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="qwTabLan">
<attribute name="title">
<string>&amp;LAN Browser</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeWidget" name="qtwLanServers">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="itemsExpandable">
<bool>false</bool>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<column>
<property name="text">
<string>Label</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="qhblLan">
<item>
<widget class="QPushButton" name="qpbLanBrowserConnect">
<property name="text">
<string>&amp;Connect</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="qpbLanBrowserCancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="qpbLanCopy">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>C&amp;opy to custom</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>qpbConnect</sender>
<signal>clicked()</signal>
<receiver>ConnectDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>21</x>
<y>248</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>541</y>
</hint>
</hints>
</connection>
<connection>
<sender>qpbCancel</sender>
<signal>clicked()</signal>
<receiver>ConnectDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>248</y>
</hint>
<hint type="destinationlabel">
<x>444</x>
<y>541</y>
</hint>
</hints>
</connection>
<connection>
<sender>qlwServers</sender>
<signal>doubleClicked(QModelIndex)</signal>
<receiver>ConnectDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>109</x>
<y>196</y>
</hint>
<hint type="destinationlabel">
<x>133</x>
<y>654</y>
</hint>
</hints>
</connection>
<connection>
<sender>qpbBrowserConnect</sender>
<signal>clicked()</signal>
<receiver>ConnectDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>119</x>
<y>263</y>
</hint>
<hint type="destinationlabel">
<x>117</x>
<y>370</y>
</hint>
</hints>
</connection>
<connection>
<sender>qpbBrowserCancel</sender>
<signal>clicked()</signal>
<receiver>ConnectDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>138</x>
<y>248</y>
</hint>
<hint type="destinationlabel">
<x>20</x>
<y>20</y>
</hint>
</hints>
</connection>
<connection>
<sender>qtwServers</sender>
<signal>doubleClicked(QModelIndex)</signal>
<receiver>ConnectDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>158</x>
<y>128</y>
</hint>
<hint type="destinationlabel">
<x>185</x>
<y>436</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -48,6 +48,7 @@ class Plugins;
class QSettings;
class Overlay;
class LCD;
class BonjourClient;
struct Global {
private:
@ -65,6 +66,7 @@ public:
QSettings *qs;
Overlay *o;
LCD *lcd;
BonjourClient *bc;
QNetworkAccessManager *nam;
int iPushToTalk;
Timer tDoublePush;

View File

@ -40,6 +40,9 @@
#include "Plugins.h"
#include "Global.h"
#include "LCD.h"
#ifdef USE_BONJOUR
#include "BonjourClient.h"
#endif
#ifdef USE_DBUS
#include "DBus.h"
#endif
@ -201,6 +204,11 @@ int main(int argc, char **argv) {
// Initialize database
g.db = new Database();
#ifdef USE_BONJOUR
// Initialize bonjour
g.bc = new BonjourClient();
#endif
// Initialize the serverhandler
g.sh = new ServerHandler();
g.sh->moveToThread(g.sh);
@ -294,6 +302,9 @@ int main(int argc, char **argv) {
delete g.p;
delete g.l;
#ifdef USE_BONJOUR
delete g.bc;
#endif
delete g.o;

View File

@ -58,6 +58,10 @@ CONFIG(no-bundled-celt) {
CONFIG *= g15
}
!CONFIG(no-bonjour) {
CONFIG *= bonjour
}
win32 {
RC_FILE = mumble.rc
HEADERS *= GlobalShortcut_win.h
@ -178,6 +182,21 @@ asio {
INCLUDEPATH *= ../../asio/common ../../asio/host ../../asio/host/pc
}
bonjour {
DEFINES *= USE_BONJOUR
HEADERS *= ../bonjour/bonjourrecord.h ../bonjour/bonjourserviceresolver.h ../bonjour/bonjourservicebrowser.h BonjourClient.h
SOURCES *= ../bonjour/bonjourserviceresolver.cpp ../bonjour/bonjourservicebrowser.cpp BonjourClient.cpp
win32 {
INCLUDEPATH *= /dev/Bonjour/include
LIBPATH *= /dev/Bonjour/lib/win32
LIBS *= -ldelayimp -lDNSSD -delayload:DNSSD.DLL
}
unix {
PKGCONFIG *= avahi-compat-libdns_sd
}
}
dbus {
DEFINES *= USE_DBUS
CONFIG *= qdbus

View File

@ -0,0 +1,51 @@
/* Copyright (C) 2009, Stefan Hacker
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "BonjourServer.h"
bool BonjourServer::bDelayLoadFailed = false;
BonjourServer::BonjourServer() : bsrRegister(NULL) {
if (bDelayLoadFailed) return;
HMODULE hLib = LoadLibrary(L"DNSSD.DLL");
if (hLib == NULL) {
bDelayLoadFailed = true;
qWarning("Bonjour: Failed to load dnssd.dll");
return;
}
FreeLibrary(hLib);
bsrRegister = new BonjourServiceRegister(this);
}
BonjourServer::~BonjourServer() {
if (bsrRegister)
delete bsrRegister;
}

View File

@ -0,0 +1,52 @@
/* Copyright (C) 2009, Stefan Hacker
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _BONJOURSERVER_H
#define _BONJOURSERVER_H
#include <delayimp.h>
#include "../Bonjour/bonjourserviceregister.h"
class BonjourServer : public QObject {
private:
Q_OBJECT
Q_DISABLE_COPY(BonjourServer)
protected:
static bool bDelayLoadFailed;
public:
BonjourServer();
~BonjourServer();
BonjourServiceRegister *bsrRegister;
};
#else
class Bonjour;
class BonjourServer;
#endif

View File

@ -188,6 +188,7 @@ void MetaParams::read(QString fname) {
qsRegPassword = qs.value("registerPassword", qsRegPassword).toString();
qsRegHost = qs.value("registerHostname", qsRegHost).toString();
qurlRegWeb = QUrl(qs.value("registerUrl", qurlRegWeb.toString()).toString());
bBonjour = qs.value("bonjour", bBonjour).toBool();
iBanTries = qs.value("autobanAttempts", iBanTries).toInt();
iBanTimeframe = qs.value("autobanTimeframe", iBanTimeframe).toInt();
@ -326,6 +327,7 @@ void MetaParams::read(QString fname) {
qmConfig.insert(QLatin1String("registerpassword"),qsRegPassword);
qmConfig.insert(QLatin1String("registerhostname"),qsRegHost);
qmConfig.insert(QLatin1String("registerurl"),qurlRegWeb.toString());
qmConfig.insert(QLatin1String("bonjour"), bBonjour ? QLatin1String("true") : QLatin1String("false"));
qmConfig.insert(QLatin1String("certificate"),qscCert.toPem());
qmConfig.insert(QLatin1String("key"),qskKey.toPem());
qmConfig.insert(QLatin1String("obfuscate"),bObfuscate ? QLatin1String("true") : QLatin1String("false"));

View File

@ -75,6 +75,7 @@ struct MetaParams {
QString qsRegPassword;
QString qsRegHost;
QUrl qurlRegWeb;
bool bBonjour;
QRegExp qrUserName;
QRegExp qrChannelName;

View File

@ -81,6 +81,9 @@ ServerUser::ServerUser(Server *p, QSslSocket *socket) : Connection(p, socket), U
Server::Server(int snum, QObject *p) : QThread(p) {
bValid = true;
iServerNum = snum;
#ifdef USE_BONJOUR
bsRegistration = NULL;
#endif
#ifdef Q_OS_UNIX
aiNotify[0] = aiNotify[1] = -1;
@ -181,7 +184,18 @@ Server::Server(int snum, QObject *p) : QThread(p) {
readLinks();
initializeCert();
initRegister();
if (bValid) {
#ifdef USE_BONJOUR
bsRegistration = new BonjourServer();
if (bsRegistration->bsrRegister) {
log("Announcing server via bonjour");
bsRegistration->bsrRegister->registerService(BonjourRecord(qsRegName, "_murmur._tcp", ""),
usPort);
}
#endif
initRegister();
}
}
void Server::startThread() {
@ -220,6 +234,11 @@ void Server::stopThread() {
}
Server::~Server() {
#ifdef USE_BONJOUR
if (bsRegistration)
delete bsRegistration;
#endif
stopThread();
#ifdef Q_OS_UNIX
@ -254,6 +273,7 @@ void Server::readParams() {
qsRegPassword = Meta::mp.qsRegPassword;
qsRegHost = Meta::mp.qsRegHost;
qurlRegWeb = Meta::mp.qurlRegWeb;
bBonjour = Meta::mp.bBonjour;
qrUserName = Meta::mp.qrUserName;
qrChannelName = Meta::mp.qrChannelName;
@ -296,6 +316,7 @@ void Server::readParams() {
qsRegPassword = getConf("registerpassword", qsRegPassword).toString();
qsRegHost = getConf("registerhostname", qsRegHost).toString();
qurlRegWeb = QUrl(getConf("registerurl", qurlRegWeb.toString()).toString());
bBonjour = getConf("bonjour", bBonjour).toBool();
qrUserName=QRegExp(getConf("username", qrUserName.pattern()).toString());
qrChannelName=QRegExp(getConf("channelname", qrChannelName.pattern()).toString());
@ -324,6 +345,8 @@ void Server::setLiveConf(const QString &key, const QString &value) {
qsRegHost = !v.isNull() ? v : Meta::mp.qsRegHost;
else if (key == "registerurl")
qurlRegWeb = !v.isNull() ? v : Meta::mp.qurlRegWeb;
else if (key == "bonjour")
bBonjour = !v.isNull() ? (v.toLower() == QLatin1String("true") || v.toLower() == QLatin1String("1") ) : Meta::mp.bBonjour;
else if (key == "username")
qrUserName=!v.isNull() ? QRegExp(v) : Meta::mp.qrUserName;
else if (key == "channelname")

View File

@ -40,6 +40,10 @@
#include "ACL.h"
#include "DBus.h"
#ifdef USE_BONJOUR
#include "BonjourServer.h"
#endif
class Channel;
class PacketDataStream;
@ -162,6 +166,10 @@ class Server : public QThread {
protected:
bool bRunning;
#ifdef USE_BONJOUR
BonjourServer *bsRegistration;
#endif
void startThread();
void stopThread();
@ -181,6 +189,7 @@ class Server : public QThread {
QString qsRegPassword;
QString qsRegHost;
QUrl qurlRegWeb;
bool bBonjour;
QRegExp qrUserName;
QRegExp qrChannelName;

View File

@ -29,6 +29,9 @@ PRECOMPILED_HEADER = murmur_pch.h
CONFIG *= dbus
}
!CONFIG(no-bonjour) {
CONFIG *= bonjour
}
win32 {
RC_FILE = murmur.rc
@ -106,3 +109,19 @@ ice {
slice.commands = /opt/Ice-3.3/bin/slice2cpp Murmur.ice
}
}
bonjour {
DEFINES *= USE_BONJOUR
HEADERS *= ../bonjour/bonjourrecord.h ../bonjour/bonjourserviceregister.h BonjourServer.h
SOURCES *= ../bonjour/bonjourserviceregister.cpp BonjourServer.cpp
win32 {
INCLUDEPATH *= /dev/Bonjour/include
LIBPATH *= /dev/Bonjour/lib/win32
LIBS *= -ldelayimp -lDNSSD -delayload:DNSSD.DLL
}
unix {
PKGCONFIG *= avahi-compat-libdns_sd
}
}