Abstract ZeroConf into a platform plugin
This commit is contained in:
parent
11efbdd1a8
commit
253972cb9a
8
debian/control
vendored
8
debian/control
vendored
@ -20,8 +20,6 @@ Build-Depends: debhelper (>= 9.0.0),
|
||||
libqt5bluetooth5,
|
||||
libqt5sql5-sqlite,
|
||||
libqt5dbus5,
|
||||
libavahi-client-dev,
|
||||
libavahi-common-dev,
|
||||
libssl-dev,
|
||||
libnymea-mqtt-dev,
|
||||
dbus-test-runner,
|
||||
@ -57,7 +55,6 @@ Depends: libqt5network5,
|
||||
libqt5bluetooth5,
|
||||
libqt5sql5-sqlite,
|
||||
logrotate,
|
||||
avahi-daemon,
|
||||
bluez,
|
||||
tar,
|
||||
iputils-tracepath,
|
||||
@ -71,6 +68,7 @@ Recommends: nymea-cli,
|
||||
network-manager,
|
||||
nymea-update-plugin-impl,
|
||||
nymea-system-plugin-impl,
|
||||
nymea-zeroconf-plugin-impl,
|
||||
Replaces: guhd
|
||||
Description: An open source IoT server - daemon
|
||||
The nymea daemon is a plugin based IoT (Internet of Things) server. The
|
||||
@ -157,8 +155,6 @@ Multi-Arch: same
|
||||
Depends: ${shlibs:Depends},
|
||||
${misc:Depends},
|
||||
libqt5bluetooth5,
|
||||
libavahi-client3,
|
||||
libavahi-common3
|
||||
Replaces: libguh1
|
||||
Description: An open source IoT server - core library
|
||||
The nymea daemon is a plugin based IoT (Internet of Things) server. The
|
||||
@ -182,8 +178,6 @@ Depends: libnymea1 (= ${binary:Version}),
|
||||
qtconnectivity5-dev,
|
||||
qttools5-dev-tools,
|
||||
libqt5websockets5-dev,
|
||||
libavahi-client-dev,
|
||||
libavahi-common-dev
|
||||
Replaces: libguh1-dev
|
||||
Description: An open source IoT server - development files
|
||||
The nymea daemon is a plugin based IoT (Internet of Things) server. The
|
||||
|
||||
4
debian/man/nymead.1
vendored
4
debian/man/nymead.1
vendored
@ -47,8 +47,8 @@ Print the debug messages from the AWS connection.
|
||||
Print the debug messages from the AWS connection traffic.
|
||||
.IP \fIApplication\fR\ (default\ enabled)
|
||||
Print the debug messages from the core application.
|
||||
.IP \fIAvahi\fR\ (default\ disabled)
|
||||
Print the debug messages from the avahi resource.
|
||||
.IP \fIPlatformZeroConfi\fR\ (default\ disabled)
|
||||
Print the debug messages from the ZeroConf resource.
|
||||
.IP \fIBluetooth\fR\ (default\ disabled)
|
||||
Print the debug messages from the bluetooth resource.
|
||||
.IP \fICloud\fR\ (default\ enabled)
|
||||
|
||||
@ -1,193 +0,0 @@
|
||||
/***
|
||||
This file is part of avahi.
|
||||
|
||||
avahi is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
avahi is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
||||
Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with avahi; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
|
||||
Modified: (C) 2016 Simon Stürz <stuerz.simon@gmail.com>
|
||||
|
||||
***/
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QSocketNotifier>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <avahi-common/timeval.h>
|
||||
|
||||
#include "qt-watch.h"
|
||||
|
||||
class AvahiWatch : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AvahiWatch(int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void* userdata);
|
||||
~AvahiWatch() { }
|
||||
AvahiWatchEvent getEvents() const { return m_incallback ? m_lastEvent : (AvahiWatchEvent)0; }
|
||||
void setWatchedEvents(AvahiWatchEvent event);
|
||||
|
||||
private slots:
|
||||
void gotIn();
|
||||
void gotOut();
|
||||
|
||||
private:
|
||||
QSocketNotifier* m_in;
|
||||
QSocketNotifier* m_out;
|
||||
AvahiWatchCallback m_callback;
|
||||
AvahiWatchEvent m_lastEvent;
|
||||
int m_fd;
|
||||
void* m_userdata;
|
||||
bool m_incallback;
|
||||
};
|
||||
|
||||
class AvahiTimeout : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AvahiTimeout(const struct timeval* tv, AvahiTimeoutCallback callback, void* userdata);
|
||||
~AvahiTimeout() {}
|
||||
void update(const struct timeval* tv);
|
||||
|
||||
private slots:
|
||||
void timeout();
|
||||
|
||||
private:
|
||||
QTimer m_timer;
|
||||
AvahiTimeoutCallback m_callback;
|
||||
void* m_userdata;
|
||||
};
|
||||
|
||||
|
||||
|
||||
AvahiWatch::AvahiWatch(int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void* userdata) :
|
||||
m_in(0),
|
||||
m_out(0),
|
||||
m_callback(callback),
|
||||
m_fd(fd),
|
||||
m_userdata(userdata),
|
||||
m_incallback(false)
|
||||
{
|
||||
setWatchedEvents(event);
|
||||
}
|
||||
|
||||
void AvahiWatch::gotIn()
|
||||
{
|
||||
m_lastEvent = AVAHI_WATCH_IN;
|
||||
m_incallback = true;
|
||||
m_callback(this, m_fd, m_lastEvent, m_userdata);
|
||||
m_incallback = false;
|
||||
}
|
||||
|
||||
void AvahiWatch::gotOut()
|
||||
{
|
||||
m_lastEvent = AVAHI_WATCH_OUT;
|
||||
m_incallback = true;
|
||||
m_callback(this, m_fd, m_lastEvent, m_userdata);
|
||||
m_incallback = false;
|
||||
}
|
||||
|
||||
void AvahiWatch::setWatchedEvents(AvahiWatchEvent event)
|
||||
{
|
||||
if (!(event & AVAHI_WATCH_IN)) { delete m_in; m_in = 0; }
|
||||
if (!(event & AVAHI_WATCH_OUT)) { delete m_out; m_out = 0; }
|
||||
if (event & AVAHI_WATCH_IN) {
|
||||
m_in = new QSocketNotifier(m_fd,QSocketNotifier::Read, this);
|
||||
connect(m_in, SIGNAL(activated(int)), SLOT(gotIn()));
|
||||
}
|
||||
if (event & AVAHI_WATCH_OUT) {
|
||||
m_out = new QSocketNotifier(m_fd, QSocketNotifier::Write, this);
|
||||
connect(m_out, SIGNAL(activated(int)), SLOT(gotOut()));
|
||||
}
|
||||
}
|
||||
|
||||
AvahiTimeout::AvahiTimeout(const struct timeval* tv, AvahiTimeoutCallback callback, void *userdata) :
|
||||
m_callback(callback),
|
||||
m_userdata(userdata)
|
||||
{
|
||||
connect(&m_timer, SIGNAL(timeout()), this, SLOT(timeout()));
|
||||
m_timer.setSingleShot(true);
|
||||
update(tv);
|
||||
}
|
||||
|
||||
void AvahiTimeout::update(const struct timeval *tv)
|
||||
{
|
||||
m_timer.stop();
|
||||
if (tv) {
|
||||
AvahiUsec u = avahi_age(tv)/1000;
|
||||
m_timer.start( (u>0) ? 0 : -u);
|
||||
}
|
||||
}
|
||||
|
||||
void AvahiTimeout::timeout()
|
||||
{
|
||||
m_callback(this, m_userdata);
|
||||
}
|
||||
|
||||
static AvahiWatch* q_watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata)
|
||||
{
|
||||
Q_UNUSED(api)
|
||||
return new AvahiWatch(fd, event, callback, userdata);
|
||||
}
|
||||
|
||||
static void q_watch_update(AvahiWatch *w, AvahiWatchEvent events)
|
||||
{
|
||||
w->setWatchedEvents(events);
|
||||
}
|
||||
|
||||
static AvahiWatchEvent q_watch_get_events(AvahiWatch *w)
|
||||
{
|
||||
return w->getEvents();
|
||||
}
|
||||
|
||||
static void q_watch_free(AvahiWatch *w)
|
||||
{
|
||||
delete w;
|
||||
}
|
||||
|
||||
static AvahiTimeout* q_timeout_new(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata)
|
||||
{
|
||||
Q_UNUSED(api)
|
||||
return new AvahiTimeout(tv, callback, userdata);
|
||||
}
|
||||
|
||||
static void q_timeout_update(AvahiTimeout *t, const struct timeval *tv)
|
||||
{
|
||||
t->update(tv);
|
||||
}
|
||||
|
||||
static void q_timeout_free(AvahiTimeout *t)
|
||||
{
|
||||
delete t;
|
||||
}
|
||||
|
||||
const AvahiPoll* avahi_qt_poll_get(void)
|
||||
{
|
||||
static const AvahiPoll qt_poll = {
|
||||
NULL,
|
||||
q_watch_new,
|
||||
q_watch_update,
|
||||
q_watch_get_events,
|
||||
q_watch_free,
|
||||
q_timeout_new,
|
||||
q_timeout_update,
|
||||
q_timeout_free
|
||||
};
|
||||
|
||||
return &qt_poll;
|
||||
}
|
||||
|
||||
#include "qt-watch.moc"
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
#ifndef QAVAHI_H
|
||||
#define QAVAHI_H
|
||||
|
||||
/***
|
||||
This file is part of avahi.
|
||||
|
||||
avahi is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
avahi is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
||||
Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with avahi; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
USA.
|
||||
|
||||
Modified: (C) 2016 Simon Stürz <stuerz.simon@gmail.com>
|
||||
|
||||
***/
|
||||
|
||||
/** \file qt-watch.h Qt main loop adapter */
|
||||
|
||||
#include <avahi-common/watch.h>
|
||||
|
||||
AVAHI_C_DECL_BEGIN
|
||||
|
||||
/** Setup abstract poll structure for integration with Qt main loop */
|
||||
const AvahiPoll* avahi_qt_poll_get(void);
|
||||
|
||||
AVAHI_C_DECL_END
|
||||
|
||||
#endif // QAVAHI_H
|
||||
@ -1,136 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "qt-watch.h"
|
||||
#include "qtavahiclient.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
#include "qtavahiservicebrowserimplementation.h"
|
||||
#include "qtavahiservicebrowserimplementation_p.h"
|
||||
|
||||
#include <avahi-common/error.h>
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
QtAvahiClient::QtAvahiClient(QObject *parent) :
|
||||
QObject(parent),
|
||||
m_poll(avahi_qt_poll_get()),
|
||||
m_client(nullptr),
|
||||
error(0),
|
||||
m_state(QtAvahiClientStateNone)
|
||||
{
|
||||
connect(this, &QtAvahiClient::clientStateChangedInternal, this, &QtAvahiClient::onClientStateChanged);
|
||||
}
|
||||
|
||||
QtAvahiClient::~QtAvahiClient()
|
||||
{
|
||||
if (m_client)
|
||||
avahi_client_free(m_client);
|
||||
|
||||
}
|
||||
|
||||
QtAvahiClient::QtAvahiClientState QtAvahiClient::state() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
void QtAvahiClient::start()
|
||||
{
|
||||
if (m_client)
|
||||
return;
|
||||
|
||||
m_client = avahi_client_new(m_poll, (AvahiClientFlags) 0, QtAvahiClient::callback, this, &error);
|
||||
}
|
||||
|
||||
void QtAvahiClient::stop()
|
||||
{
|
||||
if (m_client)
|
||||
avahi_client_free(m_client);
|
||||
|
||||
m_client = nullptr;
|
||||
}
|
||||
|
||||
QString QtAvahiClient::errorString() const
|
||||
{
|
||||
return QString(avahi_strerror(error));
|
||||
}
|
||||
|
||||
void QtAvahiClient::callback(AvahiClient *client, AvahiClientState state, void *userdata)
|
||||
{
|
||||
QtAvahiClient *serviceClient = static_cast<QtAvahiClient *>(userdata);
|
||||
if (!serviceClient)
|
||||
return;
|
||||
|
||||
serviceClient->m_client = client;
|
||||
|
||||
switch (state) {
|
||||
case AVAHI_CLIENT_S_RUNNING:
|
||||
emit serviceClient->clientStateChangedInternal(QtAvahiClientStateRunning);
|
||||
break;
|
||||
case AVAHI_CLIENT_FAILURE:
|
||||
emit serviceClient->clientStateChangedInternal(QtAvahiClientStateFailure);
|
||||
break;
|
||||
case AVAHI_CLIENT_S_COLLISION:
|
||||
emit serviceClient->clientStateChangedInternal(QtAvahiClientStateCollision);
|
||||
break;
|
||||
case AVAHI_CLIENT_S_REGISTERING:
|
||||
emit serviceClient->clientStateChangedInternal(QtAvahiClientStateRegistering);
|
||||
break;
|
||||
case AVAHI_CLIENT_CONNECTING:
|
||||
emit serviceClient->clientStateChangedInternal(QtAvahiClientStateConnecting);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QtAvahiClient::onClientStateChanged(const QtAvahiClient::QtAvahiClientState &state)
|
||||
{
|
||||
if (m_state == state)
|
||||
return;
|
||||
|
||||
m_state = state;
|
||||
|
||||
// switch (m_state) {
|
||||
// case QtAvahiClientStateNone:
|
||||
// break;
|
||||
// case QtAvahiClientStateRunning:
|
||||
// qCDebug(dcAvahi()) << "Client running.";
|
||||
// break;
|
||||
// case QtAvahiClientStateFailure:
|
||||
// qCWarning(dcAvahi()) << "Client failure:" << errorString();
|
||||
// break;
|
||||
// case QtAvahiClientStateCollision:
|
||||
// qCWarning(dcAvahi()) << "Client collision:" << errorString();
|
||||
// break;
|
||||
// case QtAvahiClientStateRegistering:
|
||||
// qCDebug(dcAvahi()) << "Client registering...";
|
||||
// break;
|
||||
// case QtAvahiClientStateConnecting:
|
||||
// qCDebug(dcAvahi()) << "Client connecting...";
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
|
||||
emit clientStateChanged(m_state);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,341 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/*!
|
||||
\class nymeaserver::QtAvahiService
|
||||
\brief Allows to publish an avahi service to the network.
|
||||
|
||||
\inmodule core
|
||||
*/
|
||||
|
||||
/*! \enum QtAvahiService::QtAvahiServiceState
|
||||
|
||||
This enum type specifies the state of a \l{QtAvahiService}.
|
||||
|
||||
\value QtAvahiServiceStateUncomitted
|
||||
The group has not yet been committed, the user must still call avahi_entry_group_commit().
|
||||
\value QtAvahiServiceStateRegistering
|
||||
The entries of the group are currently being registered.
|
||||
\value QtAvahiServiceStateEstablished
|
||||
The entries have successfully been established.
|
||||
\value QtAvahiServiceStateCollision
|
||||
A name collision for one of the entries in the group has been detected, the entries have been withdrawn.
|
||||
\value QtAvahiServiceStateFailure
|
||||
Some kind of failure happened, the entries have been withdrawn.
|
||||
|
||||
*/
|
||||
|
||||
/*! \fn void QtAvahiService::serviceStateChanged(const QtAvahiServiceState &state)
|
||||
This signal will be emitted when the \a state of this \l{QtAvahiService} has changed.
|
||||
*/
|
||||
|
||||
#include "qtavahiservice.h"
|
||||
#include "qtavahiservice_p.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
#include <QNetworkInterface>
|
||||
#include <QUuid>
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
/*! Constructs a new QtAvahiService with the given \a parent. */
|
||||
QtAvahiService::QtAvahiService(QObject *parent) :
|
||||
QObject(parent),
|
||||
d_ptr(new QtAvahiServicePrivate),
|
||||
m_state(QtAvahiServiceStateUncommitted)
|
||||
{
|
||||
connect(this, &QtAvahiService::serviceStateChanged, this, &QtAvahiService::onStateChanged);
|
||||
|
||||
d_ptr->client = new QtAvahiClient(this);
|
||||
d_ptr->client->start();
|
||||
|
||||
m_reregisterTimer.setInterval(60000);
|
||||
m_reregisterTimer.setSingleShot(true);
|
||||
connect(&m_reregisterTimer, &QTimer::timeout, this, [this](){
|
||||
qCDebug(dcAvahiDebug()) << "Re-registering service" << this;
|
||||
resetService(true);
|
||||
registerService(m_name, m_hostAddress, m_port, m_serviceType, m_txtRecords, true);
|
||||
});
|
||||
}
|
||||
|
||||
/*! Destructs this \l{QtAvahiService}. */
|
||||
QtAvahiService::~QtAvahiService()
|
||||
{
|
||||
if (d_ptr->group) {
|
||||
if (d_ptr->serviceList) {
|
||||
avahi_string_list_free(d_ptr->serviceList);
|
||||
}
|
||||
avahi_entry_group_free(d_ptr->group);
|
||||
}
|
||||
|
||||
delete d_ptr;
|
||||
}
|
||||
|
||||
/*! Returns the hostAddress of this \l{QtAvahiService}. */
|
||||
QHostAddress QtAvahiService::hostAddress() const
|
||||
{
|
||||
return d_ptr->hostAddress;
|
||||
}
|
||||
|
||||
/*! Returns the port of this \l{QtAvahiService}. */
|
||||
quint16 QtAvahiService::port() const
|
||||
{
|
||||
return d_ptr->port;
|
||||
}
|
||||
|
||||
/*! Returns the name of this \l{QtAvahiService}. */
|
||||
QString QtAvahiService::name() const
|
||||
{
|
||||
return d_ptr->name;
|
||||
}
|
||||
|
||||
/*! Returns the service type of this \l{QtAvahiService}. */
|
||||
QString QtAvahiService::serviceType() const
|
||||
{
|
||||
return d_ptr->type;
|
||||
}
|
||||
|
||||
QHash<QString, QString> QtAvahiService::txtRecords() const
|
||||
{
|
||||
return d_ptr->txtRecords;
|
||||
}
|
||||
|
||||
QtAvahiService::QtAvahiServiceState QtAvahiService::state() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
/*! Register a new \l{QtAvahiService} with the given \a name and \a port. The service type can be specified with the \a serviceType string. The \a txtRecords records inform about additional information. Returns true if the service could be registered. */
|
||||
bool QtAvahiService::registerService(const QString &name, const QHostAddress &hostAddress, const quint16 &port, const QString &serviceType, const QHash<QString, QString> &txtRecords, bool silent)
|
||||
{
|
||||
// Check if the client is running
|
||||
if (!d_ptr->client->m_client || AVAHI_CLIENT_S_RUNNING != avahi_client_get_state(d_ptr->client->m_client)) {
|
||||
qCWarning(dcAvahi()) << "Could not register service" << name << port << serviceType << ". The client is not available.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cache all values locally at first
|
||||
m_name = name;
|
||||
m_hostAddress = hostAddress;
|
||||
m_port = port;
|
||||
m_serviceType = serviceType;
|
||||
m_txtRecords = txtRecords;
|
||||
|
||||
// Now set up avahi
|
||||
d_ptr->name = name;
|
||||
d_ptr->hostAddress = hostAddress;
|
||||
d_ptr->port = port;
|
||||
d_ptr->type = serviceType;
|
||||
d_ptr->txtRecords = txtRecords;
|
||||
|
||||
// If the group is not set yet, create it
|
||||
if (!d_ptr->group)
|
||||
d_ptr->group = avahi_entry_group_new(d_ptr->client->m_client, QtAvahiServicePrivate::callback, this);
|
||||
|
||||
// If the group is empty
|
||||
if (avahi_entry_group_is_empty(d_ptr->group)) {
|
||||
// Add the service
|
||||
AvahiIfIndex ifIndex = AVAHI_IF_UNSPEC;
|
||||
if (hostAddress != QHostAddress("0.0.0.0")) {
|
||||
foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) {
|
||||
foreach (const QNetworkAddressEntry &addressEntry, interface.addressEntries()) {
|
||||
QPair<QHostAddress, int> subnet = QHostAddress::parseSubnet(addressEntry.ip().toString() + "/" + addressEntry.netmask().toString());
|
||||
if (hostAddress.isInSubnet(subnet.first, subnet.second)) {
|
||||
ifIndex = interface.index();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug((silent ? dcAvahiDebug() : dcAvahi())) << "Registering avahi service" << name << hostAddress.toString() << port << serviceType << "on interface" << ifIndex;
|
||||
|
||||
d_ptr->serviceList = QtAvahiServicePrivate::createTxtList(txtRecords);
|
||||
d_ptr->error = avahi_entry_group_add_service_strlst(d_ptr->group,
|
||||
ifIndex,
|
||||
hostAddress.protocol() == QAbstractSocket::IPv6Protocol ? AVAHI_PROTO_INET6 : AVAHI_PROTO_INET,
|
||||
(AvahiPublishFlags) 0,
|
||||
d_ptr->name.toLatin1().data(),
|
||||
d_ptr->type.toLatin1().data(),
|
||||
0,
|
||||
0,
|
||||
(uint16_t)d_ptr->port,
|
||||
d_ptr->serviceList);
|
||||
|
||||
// Verify if the group has to be comitted
|
||||
if (d_ptr->error) {
|
||||
|
||||
if (d_ptr->error == AVAHI_ERR_COLLISION) {
|
||||
if (!handleCollision()) {
|
||||
qCWarning(dcAvahi()) << this << "error:" << avahi_strerror(d_ptr->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
qCWarning(dcAvahi()) << this << "error:" << avahi_strerror(d_ptr->error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Commit the service
|
||||
d_ptr->error = avahi_entry_group_commit(d_ptr->group);
|
||||
if (d_ptr->error) {
|
||||
qCWarning(dcAvahi()) << this << "error:" << avahi_strerror(d_ptr->error);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcAvahi()) << "Service already registered. Please reset the service before reusing it.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reregister every minute in order to work around low quality network hardware which
|
||||
// doesn't properly keep multicast sessions alive.
|
||||
// https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=736641
|
||||
m_reregisterTimer.start();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! Remove this service from the local network. This \l{QtAvahiService} can be reused to register a new avahi service. */
|
||||
void QtAvahiService::resetService(bool silent)
|
||||
{
|
||||
if (!d_ptr->group) {
|
||||
qCWarning(dcAvahi()) << "Cannot unregister service. Service Group not existing.";
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug((silent ? dcAvahiDebug() : dcAvahi())) << "Unregistering service" << this;
|
||||
|
||||
if (d_ptr->serviceList) {
|
||||
avahi_string_list_free(d_ptr->serviceList);
|
||||
d_ptr->serviceList = nullptr;
|
||||
}
|
||||
avahi_entry_group_reset(d_ptr->group);
|
||||
m_reregisterTimer.stop();
|
||||
}
|
||||
|
||||
/*! Update the TXT record of this service. Returns true of the record could be updated. */
|
||||
bool QtAvahiService::updateTxtRecord(const QHash<QString, QString> &txtRecords)
|
||||
{
|
||||
if (!d_ptr->group)
|
||||
return false;
|
||||
|
||||
m_txtRecords = txtRecords;
|
||||
|
||||
// Add the service
|
||||
AvahiIfIndex ifIndex = AVAHI_IF_UNSPEC;
|
||||
if (d_ptr->hostAddress != QHostAddress("0.0.0.0")) {
|
||||
foreach (const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) {
|
||||
foreach (const QNetworkAddressEntry &addressEntry, interface.addressEntries()) {
|
||||
QPair<QHostAddress, int> subnet = QHostAddress::parseSubnet(addressEntry.ip().toString() + "/" + addressEntry.netmask().toString());
|
||||
if (d_ptr->hostAddress.isInSubnet(subnet.first, subnet.second)) {
|
||||
ifIndex = interface.index();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d_ptr->serviceList = QtAvahiServicePrivate::createTxtList(txtRecords);
|
||||
d_ptr->error = avahi_entry_group_update_service_txt_strlst(d_ptr->group,
|
||||
ifIndex,
|
||||
d_ptr->hostAddress.protocol() == QAbstractSocket::IPv6Protocol ? AVAHI_PROTO_INET6 : AVAHI_PROTO_INET,
|
||||
(AvahiPublishFlags) 0,
|
||||
d_ptr->name.toLatin1().data(),
|
||||
d_ptr->type.toLatin1().data(),
|
||||
0,
|
||||
d_ptr->serviceList);
|
||||
|
||||
// Verify if the group has to be comitted
|
||||
if (d_ptr->error) {
|
||||
qCWarning(dcAvahi()) << this << "error:" << avahi_strerror(d_ptr->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
qCDebug(dcAvahi()) << this << "updated TXT record.";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! Returns true if the service group was added and committed to the network without errors. */
|
||||
bool QtAvahiService::isValid() const
|
||||
{
|
||||
return (d_ptr->group && !d_ptr->error);
|
||||
}
|
||||
|
||||
/*! Returns the error string of this \l{QtAvahiService}. */
|
||||
QString QtAvahiService::errorString() const
|
||||
{
|
||||
if (!d_ptr->client->m_client)
|
||||
return "Invalid client.";
|
||||
|
||||
return avahi_strerror(avahi_client_errno(d_ptr->client->m_client));
|
||||
}
|
||||
|
||||
bool QtAvahiService::handleCollision()
|
||||
{
|
||||
char* alt = avahi_alternative_service_name(name().toStdString().data());
|
||||
QString alternativeServiceName = QLatin1String(alt);
|
||||
free(alt);
|
||||
qCDebug(dcAvahi()) << "Service name collision. Picking alternative service name" << alternativeServiceName;
|
||||
|
||||
resetService();
|
||||
return registerService(alternativeServiceName, hostAddress(), port(), serviceType(), txtRecords());
|
||||
}
|
||||
|
||||
void QtAvahiService::onStateChanged(const QtAvahiServiceState &state)
|
||||
{
|
||||
if (m_state == state)
|
||||
return;
|
||||
|
||||
m_state = state;
|
||||
|
||||
switch (m_state) {
|
||||
case QtAvahiServiceStateUncommitted:
|
||||
qCDebug(dcAvahiDebug()) << "Service state changed to Uncommitted:" << this;
|
||||
break;
|
||||
case QtAvahiServiceStateRegistering:
|
||||
qCDebug(dcAvahiDebug()) << "Service state changed to Registering:" << this;
|
||||
break;
|
||||
case QtAvahiServiceStateEstablished:
|
||||
qCDebug(dcAvahiDebug()) << "Service state changed to Established:" << this;
|
||||
break;
|
||||
case QtAvahiServiceStateCollision:
|
||||
qCDebug(dcAvahiDebug()) << "Service state changed to Collision:" << this;
|
||||
handleCollision();
|
||||
break;
|
||||
case QtAvahiServiceStateFailure:
|
||||
qCDebug(dcAvahiDebug()) << "Service state changed to Failure:" << this;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QDebug operator <<(QDebug dbg, QtAvahiService *service)
|
||||
{
|
||||
dbg.nospace() << "AvahiService(";
|
||||
dbg << service->name() << ", " << service->serviceType() << ", " << service->port() << ") ";
|
||||
return dbg;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,96 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef QTAVAHISERVICE_H
|
||||
#define QTAVAHISERVICE_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
#include <QHostAddress>
|
||||
#include <QTimer>
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
class QtAvahiServicePrivate;
|
||||
|
||||
class QtAvahiService : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum QtAvahiServiceState {
|
||||
QtAvahiServiceStateUncommitted = 0,
|
||||
QtAvahiServiceStateRegistering = 1,
|
||||
QtAvahiServiceStateEstablished = 2,
|
||||
QtAvahiServiceStateCollision = 3,
|
||||
QtAvahiServiceStateFailure = 4
|
||||
};
|
||||
Q_ENUM(QtAvahiServiceState)
|
||||
|
||||
explicit QtAvahiService(QObject *parent = nullptr);
|
||||
~QtAvahiService();
|
||||
|
||||
QHostAddress hostAddress() const;
|
||||
quint16 port() const;
|
||||
QString name() const;
|
||||
QString serviceType() const;
|
||||
QHash<QString, QString> txtRecords() const;
|
||||
QtAvahiServiceState state() const;
|
||||
|
||||
bool registerService(const QString &name, const QHostAddress &hostAddress, const quint16 &port, const QString &serviceType = "_http._tcp", const QHash<QString, QString> &txtRecords = QHash<QString, QString>(), bool silent = false);
|
||||
void resetService(bool silent = false);
|
||||
|
||||
bool updateTxtRecord(const QHash<QString, QString> &txtRecords);
|
||||
|
||||
bool isValid() const;
|
||||
QString errorString() const;
|
||||
|
||||
signals:
|
||||
void serviceStateChanged(const QtAvahiServiceState &state);
|
||||
|
||||
protected:
|
||||
QtAvahiServicePrivate *d_ptr;
|
||||
|
||||
private slots:
|
||||
bool handleCollision();
|
||||
void onStateChanged(const QtAvahiServiceState &state);
|
||||
|
||||
private:
|
||||
QtAvahiServiceState m_state;
|
||||
Q_DECLARE_PRIVATE(QtAvahiService)
|
||||
|
||||
QTimer m_reregisterTimer;
|
||||
|
||||
QString m_name;
|
||||
QHostAddress m_hostAddress;
|
||||
quint16 m_port;
|
||||
QString m_serviceType;
|
||||
QHash<QString, QString> m_txtRecords;
|
||||
};
|
||||
|
||||
QDebug operator <<(QDebug dbg, QtAvahiService *service);
|
||||
|
||||
}
|
||||
|
||||
#endif // QTAVAHISERVICE_H
|
||||
@ -1,85 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "qtavahiservice_p.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QHash>
|
||||
#include <QStringList>
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
QtAvahiServicePrivate::QtAvahiServicePrivate() :
|
||||
client(0),
|
||||
group(0),
|
||||
error(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void QtAvahiServicePrivate::callback(AvahiEntryGroup *group, AvahiEntryGroupState state, void *userdata)
|
||||
{
|
||||
Q_UNUSED(group);
|
||||
|
||||
QtAvahiService *service = static_cast<QtAvahiService *>(userdata);
|
||||
if (!service)
|
||||
return;
|
||||
|
||||
if (service->state() == (QtAvahiService::QtAvahiServiceState)state)
|
||||
return;
|
||||
|
||||
switch (state) {
|
||||
case AVAHI_ENTRY_GROUP_UNCOMMITED:
|
||||
emit service->serviceStateChanged(QtAvahiService::QtAvahiServiceStateUncommitted);
|
||||
break;
|
||||
case AVAHI_ENTRY_GROUP_REGISTERING:
|
||||
emit service->serviceStateChanged(QtAvahiService::QtAvahiServiceStateRegistering);
|
||||
break;
|
||||
case AVAHI_ENTRY_GROUP_ESTABLISHED:
|
||||
emit service->serviceStateChanged(QtAvahiService::QtAvahiServiceStateEstablished);
|
||||
break;
|
||||
case AVAHI_ENTRY_GROUP_COLLISION:
|
||||
emit service->serviceStateChanged(QtAvahiService::QtAvahiServiceStateCollision);
|
||||
break;
|
||||
case AVAHI_ENTRY_GROUP_FAILURE:
|
||||
emit service->serviceStateChanged(QtAvahiService::QtAvahiServiceStateFailure);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AvahiStringList *QtAvahiServicePrivate::createTxtList(const QHash<QString, QString> &txt)
|
||||
{
|
||||
AvahiStringList *list = nullptr;
|
||||
if (txt.isEmpty())
|
||||
return list;
|
||||
|
||||
const QStringList keys = txt.keys();
|
||||
list = avahi_string_list_new((keys.first() + '=' + txt[keys.first()]).toLatin1().constData(), nullptr);
|
||||
for (const QString &key : keys.mid(1)) {
|
||||
list = avahi_string_list_add_pair(list, key.toLatin1().constData(), txt[key].toLatin1().constData());
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,122 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/*!
|
||||
\class nymeaserver::QtAvahiServiceBrowserImplementation
|
||||
\brief Allows to browse avahi services in the local network.
|
||||
|
||||
\ingroup hardware
|
||||
\inmodule libnymea
|
||||
*/
|
||||
|
||||
#include "qtavahiservicebrowserimplementation.h"
|
||||
#include "qtavahiservicebrowserimplementation_p.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
#include <avahi-common/error.h>
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
/*! Constructs a new \l{QtAvahiServiceBrowserImplementation} with the given \a parent. */
|
||||
QtAvahiServiceBrowserImplementation::QtAvahiServiceBrowserImplementation(QObject *parent) :
|
||||
QtAvahiServiceBrowser(parent),
|
||||
d_ptr(new QtAvahiServiceBrowserImplementationPrivate(new QtAvahiClient))
|
||||
{
|
||||
// TODO: check available here
|
||||
m_available = true;
|
||||
|
||||
connect(d_ptr->client, &QtAvahiClient::clientStateChanged, this, &QtAvahiServiceBrowserImplementation::onClientStateChanged);
|
||||
|
||||
qCDebug(dcAvahiDebug()) << "-->" << name() << "created successfully.";
|
||||
}
|
||||
|
||||
/*! Destructs this \l{QtAvahiServiceBrowserImplementation}. */
|
||||
QtAvahiServiceBrowserImplementation::~QtAvahiServiceBrowserImplementation()
|
||||
{
|
||||
// Delete each service browser
|
||||
foreach (const QString &serviceType, d_ptr->serviceBrowserTable.keys()) {
|
||||
AvahiServiceBrowser *browser = d_ptr->serviceBrowserTable.take(serviceType);
|
||||
if (browser) {
|
||||
avahi_service_browser_free(browser);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the service type browser
|
||||
if (d_ptr->serviceTypeBrowser)
|
||||
avahi_service_type_browser_free(d_ptr->serviceTypeBrowser);
|
||||
|
||||
delete d_ptr;
|
||||
}
|
||||
|
||||
/*! Returns the current \l{AvahiServiceEntry} list of this \l{QtAvahiServiceBrowserImplementation}. */
|
||||
QList<AvahiServiceEntry> QtAvahiServiceBrowserImplementation::serviceEntries() const
|
||||
{
|
||||
return m_serviceEntries;
|
||||
}
|
||||
|
||||
bool QtAvahiServiceBrowserImplementation::available() const
|
||||
{
|
||||
return m_available;
|
||||
}
|
||||
|
||||
bool QtAvahiServiceBrowserImplementation::enabled() const
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
void QtAvahiServiceBrowserImplementation::onClientStateChanged(const QtAvahiClient::QtAvahiClientState &state)
|
||||
{
|
||||
if (state == QtAvahiClient::QtAvahiClientStateRunning) {
|
||||
qCDebug(dcAvahiDebug()) << "Service browser client connected.";
|
||||
// Return if we already have a service type browser
|
||||
if (d_ptr->serviceTypeBrowser)
|
||||
return;
|
||||
|
||||
d_ptr->serviceTypeBrowser = avahi_service_type_browser_new(d_ptr->client->m_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, (AvahiLookupFlags) 0, QtAvahiServiceBrowserImplementationPrivate::callbackServiceTypeBrowser, this);
|
||||
} else if (state == QtAvahiClient::QtAvahiClientStateFailure) {
|
||||
qCWarning(dcAvahi()) << name() << "client failure:" << d_ptr->client->errorString();
|
||||
}
|
||||
}
|
||||
|
||||
void QtAvahiServiceBrowserImplementation::setEnabled(bool enabled)
|
||||
{
|
||||
if (m_enabled == enabled) {
|
||||
qCDebug(dcAvahi()) << "Avahi Service Browser already" << (enabled ? "enabled" : "disabled") << "... Not changing state.";
|
||||
return;
|
||||
}
|
||||
if (enabled) {
|
||||
d_ptr->client->start();
|
||||
qCDebug(dcAvahi()) << "Avahi Service Browser enabled";
|
||||
} else {
|
||||
d_ptr->client->stop();
|
||||
qCDebug(dcAvahi()) << "Avahi Service Browser disabled";
|
||||
}
|
||||
}
|
||||
|
||||
void QtAvahiServiceBrowserImplementation::createServiceBrowser(const char *serviceType)
|
||||
{
|
||||
// create a new service browser for the given serviceType
|
||||
AvahiServiceBrowser *browser = avahi_service_browser_new(d_ptr->client->m_client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, serviceType, NULL, (AvahiLookupFlags) 0, QtAvahiServiceBrowserImplementationPrivate::callbackServiceBrowser, this);
|
||||
d_ptr->serviceBrowserTable.insert(serviceType, browser);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,223 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "qtavahiservicebrowserimplementation_p.h"
|
||||
#include "qtavahiservicebrowserimplementation.h"
|
||||
#include "network/avahi/avahiserviceentry.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
#include <avahi-common/strlst.h>
|
||||
#include <avahi-common/error.h>
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
QtAvahiServiceBrowserImplementationPrivate::QtAvahiServiceBrowserImplementationPrivate(QtAvahiClient *client) :
|
||||
client(client),
|
||||
serviceTypeBrowser(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QtAvahiServiceBrowserImplementationPrivate::~QtAvahiServiceBrowserImplementationPrivate()
|
||||
{
|
||||
foreach (AvahiServiceResolver *resolver, m_serviceResolvers) {
|
||||
avahi_service_resolver_free(resolver);
|
||||
}
|
||||
}
|
||||
|
||||
void QtAvahiServiceBrowserImplementationPrivate::callbackServiceTypeBrowser(AvahiServiceTypeBrowser *browser, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata)
|
||||
{
|
||||
Q_UNUSED(browser)
|
||||
Q_UNUSED(interface)
|
||||
Q_UNUSED(protocol)
|
||||
Q_UNUSED(domain)
|
||||
Q_UNUSED(flags)
|
||||
|
||||
QtAvahiServiceBrowserImplementation *serviceBrowser = static_cast<QtAvahiServiceBrowserImplementation *>(userdata);
|
||||
if (!serviceBrowser)
|
||||
return;
|
||||
|
||||
switch (event) {
|
||||
case AVAHI_BROWSER_NEW:
|
||||
if (!serviceBrowser->m_serviceTypes.contains(type)) {
|
||||
serviceBrowser->m_serviceTypes.append(type);
|
||||
qCDebug(dcAvahiDebug()) << "[+] Service browser" << type;
|
||||
serviceBrowser->createServiceBrowser(type);
|
||||
}
|
||||
break;
|
||||
case AVAHI_BROWSER_REMOVE:
|
||||
// Note: the browser for this serviceType will be deleted once all
|
||||
// services from this type are removed
|
||||
break;
|
||||
case AVAHI_BROWSER_CACHE_EXHAUSTED:
|
||||
break;
|
||||
case AVAHI_BROWSER_ALL_FOR_NOW:
|
||||
break;
|
||||
case AVAHI_BROWSER_FAILURE:
|
||||
qCWarning(dcAvahi()) << "Service type browser error:" << QString(avahi_strerror(avahi_client_errno(serviceBrowser->d_ptr->client->m_client)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QtAvahiServiceBrowserImplementationPrivate::callbackServiceBrowser(AvahiServiceBrowser *browser, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata)
|
||||
{
|
||||
Q_UNUSED(browser);
|
||||
Q_UNUSED(flags);
|
||||
|
||||
QtAvahiServiceBrowserImplementation *serviceBrowser = static_cast<QtAvahiServiceBrowserImplementation *>(userdata);
|
||||
if (!serviceBrowser)
|
||||
return;
|
||||
|
||||
switch (event) {
|
||||
case AVAHI_BROWSER_NEW: {
|
||||
// Start resolving new service
|
||||
AvahiServiceResolver *resolver = avahi_service_resolver_new(serviceBrowser->d_ptr->client->m_client,
|
||||
interface,
|
||||
protocol,
|
||||
name,
|
||||
type,
|
||||
domain,
|
||||
AVAHI_PROTO_UNSPEC,
|
||||
(AvahiLookupFlags) 0,
|
||||
QtAvahiServiceBrowserImplementationPrivate::callbackServiceResolver,
|
||||
serviceBrowser);
|
||||
if (resolver) {
|
||||
serviceBrowser->d_ptr->m_serviceResolvers.append(resolver);
|
||||
} else {
|
||||
qCWarning(dcAvahi()) << "Failed to resolve service" << QString(name) << ":" << avahi_strerror(avahi_client_errno(serviceBrowser->d_ptr->client->m_client));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AVAHI_BROWSER_REMOVE: {
|
||||
// Remove the service
|
||||
foreach (const AvahiServiceEntry &entry, serviceBrowser->m_serviceEntries) {
|
||||
// Check not only the name, but also the protocol
|
||||
if (entry.name() == name && entry.protocol() == QtAvahiServiceBrowserImplementationPrivate::convertProtocol(protocol)) {
|
||||
serviceBrowser->m_serviceEntries.removeAll(entry);
|
||||
emit serviceBrowser->serviceEntryRemoved(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this was the last service for this serviceType
|
||||
foreach (const AvahiServiceEntry &entry, serviceBrowser->m_serviceEntries) {
|
||||
if (entry.serviceType() == type)
|
||||
return;
|
||||
}
|
||||
|
||||
// This was the last service for this serviceType, lets delete the corresponding browser
|
||||
AvahiServiceBrowser *browser = serviceBrowser->d_ptr->serviceBrowserTable.take(type);
|
||||
if (browser)
|
||||
avahi_service_browser_free(browser);
|
||||
|
||||
serviceBrowser->m_serviceTypes.removeAll(type);
|
||||
break;
|
||||
}
|
||||
case AVAHI_BROWSER_ALL_FOR_NOW:
|
||||
break;
|
||||
case AVAHI_BROWSER_CACHE_EXHAUSTED:
|
||||
break;
|
||||
case AVAHI_BROWSER_FAILURE:
|
||||
qCWarning(dcAvahi()) << "Service browser error:" << QString(avahi_strerror(avahi_client_errno(serviceBrowser->d_ptr->client->m_client)));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QtAvahiServiceBrowserImplementationPrivate::callbackServiceResolver(AvahiServiceResolver *resolver, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata)
|
||||
{
|
||||
Q_UNUSED(interface);
|
||||
Q_UNUSED(type);
|
||||
Q_UNUSED(txt);
|
||||
|
||||
QPointer<QtAvahiServiceBrowserImplementation> serviceBrowser = static_cast<QtAvahiServiceBrowserImplementation *>(userdata);
|
||||
if (serviceBrowser.isNull())
|
||||
return;
|
||||
|
||||
switch (event) {
|
||||
case AVAHI_RESOLVER_FAILURE:
|
||||
break;
|
||||
case AVAHI_RESOLVER_FOUND: {
|
||||
char a[AVAHI_ADDRESS_STR_MAX];
|
||||
avahi_address_snprint(a, sizeof(a), address);
|
||||
|
||||
// convert protocol
|
||||
QAbstractSocket::NetworkLayerProtocol networkProtocol = QtAvahiServiceBrowserImplementationPrivate::convertProtocol(protocol);
|
||||
QStringList txtList = QtAvahiServiceBrowserImplementationPrivate::convertTxtList(txt);
|
||||
|
||||
// create the new resolved service entry
|
||||
AvahiServiceEntry entry = AvahiServiceEntry(name,
|
||||
type,
|
||||
QHostAddress(QString(a)),
|
||||
QString(domain),
|
||||
QString(host_name),
|
||||
(quint16)port,
|
||||
networkProtocol,
|
||||
txtList,
|
||||
flags);
|
||||
|
||||
serviceBrowser->m_serviceEntries.append(entry);
|
||||
emit serviceBrowser->serviceEntryAdded(entry);
|
||||
}
|
||||
}
|
||||
serviceBrowser->d_ptr->m_serviceResolvers.removeAll(resolver);
|
||||
avahi_service_resolver_free(resolver);
|
||||
|
||||
}
|
||||
|
||||
QStringList QtAvahiServiceBrowserImplementationPrivate::convertTxtList(AvahiStringList *txt)
|
||||
{
|
||||
if (!txt)
|
||||
return QStringList();
|
||||
|
||||
QStringList txtList;
|
||||
txtList.append(QString(reinterpret_cast<char *>(txt->text)));
|
||||
|
||||
while (txt->next) {
|
||||
AvahiStringList *next = txt->next;
|
||||
txtList.append(QString(reinterpret_cast<char *>(next->text)));
|
||||
txt = next;
|
||||
}
|
||||
|
||||
return txtList;
|
||||
}
|
||||
|
||||
QAbstractSocket::NetworkLayerProtocol QtAvahiServiceBrowserImplementationPrivate::convertProtocol(const AvahiProtocol &protocol)
|
||||
{
|
||||
QAbstractSocket::NetworkLayerProtocol networkProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
|
||||
|
||||
switch (protocol) {
|
||||
case AVAHI_PROTO_INET:
|
||||
networkProtocol = QAbstractSocket::IPv4Protocol;
|
||||
break;
|
||||
case AVAHI_PROTO_INET6:
|
||||
networkProtocol = QAbstractSocket::IPv6Protocol;
|
||||
break;
|
||||
case AVAHI_PROTO_UNSPEC:
|
||||
networkProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
|
||||
break;
|
||||
}
|
||||
return networkProtocol;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,89 +0,0 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef QTAVAHISERVICEBROWSERPRIVATE_H
|
||||
#define QTAVAHISERVICEBROWSERPRIVATE_H
|
||||
|
||||
#include <QStringList>
|
||||
#include <QAbstractSocket>
|
||||
#include <avahi-client/lookup.h>
|
||||
|
||||
#include "qtavahiclient.h"
|
||||
#include "qtavahiservice.h"
|
||||
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
class QtAvahiServiceTypeBrowserImplementation;
|
||||
|
||||
class QtAvahiServiceBrowserImplementationPrivate
|
||||
{
|
||||
public:
|
||||
QtAvahiServiceBrowserImplementationPrivate(QtAvahiClient *client);
|
||||
~QtAvahiServiceBrowserImplementationPrivate();
|
||||
|
||||
// Callback members
|
||||
static void callbackServiceTypeBrowser(AvahiServiceTypeBrowser *browser,
|
||||
AvahiIfIndex interface,
|
||||
AvahiProtocol protocol,
|
||||
AvahiBrowserEvent event,
|
||||
const char *type,
|
||||
const char *domain,
|
||||
AvahiLookupResultFlags flags,
|
||||
void *userdata);
|
||||
|
||||
static void callbackServiceBrowser(AvahiServiceBrowser *browser,
|
||||
AvahiIfIndex interface,
|
||||
AvahiProtocol protocol,
|
||||
AvahiBrowserEvent event,
|
||||
const char *name,
|
||||
const char *type,
|
||||
const char *domain,
|
||||
AvahiLookupResultFlags flags,
|
||||
void *userdata);
|
||||
|
||||
static void callbackServiceResolver(AvahiServiceResolver *resolver, AvahiIfIndex interface,
|
||||
AvahiProtocol protocol,
|
||||
AvahiResolverEvent event,
|
||||
const char *name,
|
||||
const char *type,
|
||||
const char *domain,
|
||||
const char *host_name,
|
||||
const AvahiAddress *address,
|
||||
uint16_t port,
|
||||
AvahiStringList *txt,
|
||||
AvahiLookupResultFlags flags,
|
||||
void *userdata);
|
||||
|
||||
// Convert members
|
||||
static QStringList convertTxtList(AvahiStringList *txt);
|
||||
static QAbstractSocket::NetworkLayerProtocol convertProtocol(const AvahiProtocol &protocol);
|
||||
|
||||
QtAvahiClient *client;
|
||||
AvahiServiceTypeBrowser *serviceTypeBrowser;
|
||||
QHash<QString, AvahiServiceBrowser *> serviceBrowserTable;
|
||||
QList<AvahiServiceResolver *> m_serviceResolvers;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QTAVAHISERVICEBROWSERPRIVATE_H
|
||||
@ -22,19 +22,24 @@
|
||||
|
||||
#include "loggingcategories.h"
|
||||
|
||||
#include "platform/platform.h"
|
||||
|
||||
#include "platform/platformzeroconfcontroller.h"
|
||||
#include "network/zeroconf/zeroconfservicebrowser.h"
|
||||
|
||||
#include "hardwaremanagerimplementation.h"
|
||||
#include "hardware/plugintimermanagerimplementation.h"
|
||||
#include "hardware/network/upnp/upnpdiscoveryimplementation.h"
|
||||
#include "hardware/network/networkaccessmanagerimpl.h"
|
||||
#include "hardware/radio433/radio433brennenstuhl.h"
|
||||
#include "hardware/bluetoothlowenergy/bluetoothlowenergymanagerimplementation.h"
|
||||
#include "hardware/network/avahi/qtavahiservicebrowserimplementation.h"
|
||||
#include "hardware/network/mqtt/mqttproviderimplementation.h"
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
HardwareManagerImplementation::HardwareManagerImplementation(MqttBroker *mqttBroker, QObject *parent) :
|
||||
HardwareManager(parent)
|
||||
HardwareManagerImplementation::HardwareManagerImplementation(Platform *platform, MqttBroker *mqttBroker, QObject *parent) :
|
||||
HardwareManager(parent),
|
||||
m_platform(platform)
|
||||
{
|
||||
// Create network access manager for all resources, centralized
|
||||
// Note: configuration and proxy settings could be implemented here
|
||||
@ -52,9 +57,6 @@ HardwareManagerImplementation::HardwareManagerImplementation(MqttBroker *mqttBro
|
||||
// UPnP discovery
|
||||
m_upnpDiscovery = new UpnpDiscoveryImplementation(m_networkAccessManager, this);
|
||||
|
||||
// Avahi Browser
|
||||
m_avahiBrowser = new QtAvahiServiceBrowserImplementation(this);
|
||||
|
||||
// Bluetooth LE
|
||||
m_bluetoothLowEnergyManager = new BluetoothLowEnergyManagerImplementation(m_pluginTimerManager->registerTimer(10), this);
|
||||
|
||||
@ -70,8 +72,8 @@ HardwareManagerImplementation::HardwareManagerImplementation(MqttBroker *mqttBro
|
||||
if (m_upnpDiscovery->available())
|
||||
setResourceEnabled(m_upnpDiscovery, true);
|
||||
|
||||
if (m_avahiBrowser->available())
|
||||
setResourceEnabled(m_avahiBrowser, true);
|
||||
if (m_platform->zeroConfController()->zeroConfServiceBrowser()->available())
|
||||
setResourceEnabled(m_platform->zeroConfController()->zeroConfServiceBrowser(), true);
|
||||
|
||||
if (m_bluetoothLowEnergyManager->available())
|
||||
setResourceEnabled(m_bluetoothLowEnergyManager, true);
|
||||
@ -103,9 +105,9 @@ UpnpDiscovery *HardwareManagerImplementation::upnpDiscovery()
|
||||
return m_upnpDiscovery;
|
||||
}
|
||||
|
||||
QtAvahiServiceBrowser *HardwareManagerImplementation::avahiBrowser()
|
||||
ZeroConfServiceBrowser *HardwareManagerImplementation::zeroConfServiceBrowser()
|
||||
{
|
||||
return m_avahiBrowser;
|
||||
return m_platform->zeroConfController()->zeroConfServiceBrowser();
|
||||
}
|
||||
|
||||
BluetoothLowEnergyManager *HardwareManagerImplementation::bluetoothLowEnergyManager()
|
||||
|
||||
@ -34,11 +34,12 @@ class UpnpDiscovery;
|
||||
class PluginTimerManager;
|
||||
class NetworkAccessManager;
|
||||
class UpnpDeviceDescriptor;
|
||||
class QtAvahiServiceBrowser;
|
||||
class ZeroConfServiceBrowser;
|
||||
class BluetoothLowEnergyManager;
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
class Platform;
|
||||
class MqttBroker;
|
||||
|
||||
class HardwareManagerImplementation : public HardwareManager
|
||||
@ -46,26 +47,27 @@ class HardwareManagerImplementation : public HardwareManager
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit HardwareManagerImplementation(MqttBroker *mqttBroker, QObject *parent = nullptr);
|
||||
explicit HardwareManagerImplementation(Platform *platform, MqttBroker *mqttBroker, QObject *parent = nullptr);
|
||||
~HardwareManagerImplementation() override;
|
||||
|
||||
Radio433 *radio433() override;
|
||||
PluginTimerManager *pluginTimerManager() override;
|
||||
NetworkAccessManager *networkManager() override;
|
||||
UpnpDiscovery *upnpDiscovery() override;
|
||||
QtAvahiServiceBrowser *avahiBrowser() override;
|
||||
ZeroConfServiceBrowser *zeroConfServiceBrowser() override;
|
||||
BluetoothLowEnergyManager *bluetoothLowEnergyManager() override;
|
||||
MqttProvider *mqttProvider() override;
|
||||
|
||||
private:
|
||||
QNetworkAccessManager *m_networkAccessManager = nullptr;
|
||||
|
||||
Platform *m_platform = nullptr;
|
||||
|
||||
// Hardware Resources
|
||||
PluginTimerManager *m_pluginTimerManager = nullptr;
|
||||
Radio433 *m_radio433 = nullptr;
|
||||
NetworkAccessManager *m_networkManager = nullptr;
|
||||
UpnpDiscovery *m_upnpDiscovery = nullptr;
|
||||
QtAvahiServiceBrowser *m_avahiBrowser = nullptr;
|
||||
BluetoothLowEnergyManager *m_bluetoothLowEnergyManager = nullptr;
|
||||
MqttProvider *m_mqttProvider = nullptr;
|
||||
};
|
||||
|
||||
@ -5,7 +5,7 @@ include(../nymea.pri)
|
||||
|
||||
QT += sql
|
||||
INCLUDEPATH += $$top_srcdir/libnymea
|
||||
LIBS += -L$$top_builddir/libnymea/ -lnymea -lssl -lcrypto -lavahi-common -lavahi-client -lnymea-mqtt
|
||||
LIBS += -L$$top_builddir/libnymea/ -lnymea -lssl -lcrypto -lnymea-mqtt
|
||||
|
||||
target.path = $$[QT_INSTALL_LIBS]
|
||||
INSTALLS += target
|
||||
@ -86,12 +86,6 @@ HEADERS += nymeacore.h \
|
||||
hardware/network/upnp/upnpdiscoveryimplementation.h \
|
||||
hardware/network/upnp/upnpdiscoveryrequest.h \
|
||||
hardware/network/upnp/upnpdiscoveryreplyimplementation.h \
|
||||
hardware/network/avahi/qt-watch.h \
|
||||
hardware/network/avahi/qtavahiclient.h \
|
||||
hardware/network/avahi/qtavahiservice.h \
|
||||
hardware/network/avahi/qtavahiservice_p.h \
|
||||
hardware/network/avahi/qtavahiservicebrowserimplementation.h \
|
||||
hardware/network/avahi/qtavahiservicebrowserimplementation_p.h \
|
||||
hardware/network/mqtt/mqttproviderimplementation.h \
|
||||
hardware/network/mqtt/mqttchannelimplementation.h \
|
||||
debugserverhandler.h \
|
||||
@ -172,12 +166,6 @@ SOURCES += nymeacore.cpp \
|
||||
hardware/network/upnp/upnpdiscoveryimplementation.cpp \
|
||||
hardware/network/upnp/upnpdiscoveryrequest.cpp \
|
||||
hardware/network/upnp/upnpdiscoveryreplyimplementation.cpp \
|
||||
hardware/network/avahi/qt-watch.cpp \
|
||||
hardware/network/avahi/qtavahiclient.cpp \
|
||||
hardware/network/avahi/qtavahiservice.cpp \
|
||||
hardware/network/avahi/qtavahiservice_p.cpp \
|
||||
hardware/network/avahi/qtavahiservicebrowserimplementation.cpp \
|
||||
hardware/network/avahi/qtavahiservicebrowserimplementation_p.cpp \
|
||||
hardware/network/mqtt/mqttproviderimplementation.cpp \
|
||||
hardware/network/mqtt/mqttchannelimplementation.cpp \
|
||||
debugserverhandler.cpp \
|
||||
|
||||
@ -161,10 +161,10 @@ void NymeaCore::init() {
|
||||
m_userManager = new UserManager(NymeaSettings::settingsPath() + "/user-db.sqlite", this);
|
||||
|
||||
qCDebug(dcApplication) << "Creating Server Manager";
|
||||
m_serverManager = new ServerManager(m_configuration, this);
|
||||
m_serverManager = new ServerManager(m_platform, m_configuration, this);
|
||||
|
||||
qCDebug(dcApplication) << "Creating Hardware Manager";
|
||||
m_hardwareManager = new HardwareManagerImplementation(m_serverManager->mqttBroker(), this);
|
||||
m_hardwareManager = new HardwareManagerImplementation(m_platform, m_serverManager->mqttBroker(), this);
|
||||
|
||||
qCDebug(dcApplication) << "Creating Device Manager (locale:" << m_configuration->locale() << ")";
|
||||
m_deviceManager = new DeviceManager(m_hardwareManager, m_configuration->locale(), this);
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include "platform.h"
|
||||
#include "platform/platformsystemcontroller.h"
|
||||
#include "platform/platformupdatecontroller.h"
|
||||
#include "platform/platformzeroconfcontroller.h"
|
||||
|
||||
#include "loggingcategories.h"
|
||||
|
||||
@ -44,27 +45,35 @@ Platform::Platform(QObject *parent) : QObject(parent)
|
||||
loadSystemPlugin(path + "/" + entry);
|
||||
} else if (entry.startsWith("libnymea_updateplugin") && entry.endsWith(".so")) {
|
||||
loadUpdatePlugin(path + "/" + entry);
|
||||
} else if (entry.startsWith("libnymea_zeroconfplugin") && entry.endsWith(".so")) {
|
||||
loadZeroConfPlugin(path + "/" + entry);
|
||||
}
|
||||
} else if (fi.isDir()) {
|
||||
if (QFileInfo::exists(path + "/" + entry + "/libnymea_systemplugin" + entry + ".so")) {
|
||||
loadSystemPlugin(path + "/" + entry + "/libnymea_systemplugin" + entry + ".so");
|
||||
} else if (QFileInfo::exists(path + "/" + entry + "/libnymea_updateplugin" + entry + ".so")) {
|
||||
loadUpdatePlugin(path + "/" + entry + "/libnymea_updateplugin" + entry + ".so");
|
||||
} else if (QFileInfo::exists(path + "/" + entry + "/libnymea_zeroconfplugin" + entry + ".so")) {
|
||||
loadZeroConfPlugin(path + "/" + entry + "/libnymea_zeroconfplugin" + entry + ".so");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_platformSystemController && m_platformUpdateController) {
|
||||
if (m_platformSystemController && m_platformUpdateController && m_platformZeroConfController) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!m_platformSystemController) {
|
||||
qCWarning(dcPlatform()) << "Could not load a system plugin. System control features won't be available.";
|
||||
qCWarning(dcPlatform()) << "No system plugin loaded. System control features won't be available.";
|
||||
m_platformSystemController = new PlatformSystemController(this);
|
||||
}
|
||||
if (!m_platformUpdateController) {
|
||||
qCWarning(dcPlatform()) << "Could not load an update plugin. System update features won't be available.";
|
||||
qCWarning(dcPlatform()) << "No update plugin loaded. System update features won't be available.";
|
||||
m_platformUpdateController = new PlatformUpdateController(this);
|
||||
}
|
||||
if (!m_platformZeroConfController) {
|
||||
qCWarning(dcPlatform()) << "No ZeroConf plugin loaded. ZeroConf will not be available.";
|
||||
m_platformZeroConfController = new PlatformZeroConfController(this);
|
||||
}
|
||||
}
|
||||
|
||||
PlatformSystemController *Platform::systemController() const
|
||||
@ -77,6 +86,11 @@ PlatformUpdateController *Platform::updateController() const
|
||||
return m_platformUpdateController;
|
||||
}
|
||||
|
||||
PlatformZeroConfController *Platform::zeroConfController() const
|
||||
{
|
||||
return m_platformZeroConfController;
|
||||
}
|
||||
|
||||
QStringList Platform::pluginSearchDirs() const
|
||||
{
|
||||
QStringList searchDirs;
|
||||
@ -103,16 +117,16 @@ void Platform::loadSystemPlugin(const QString &file)
|
||||
loader.setFileName(file);
|
||||
loader.setLoadHints(QLibrary::ResolveAllSymbolsHint);
|
||||
if (!loader.load()) {
|
||||
qCWarning(dcPlatform) << "Could not load plugin data of" << file << "\n" << loader.errorString();
|
||||
qCWarning(dcPlatform) << loader.errorString();
|
||||
return;
|
||||
}
|
||||
m_platformSystemController = qobject_cast<PlatformSystemController*>(loader.instance());
|
||||
if (!m_platformSystemController) {
|
||||
qCWarning(dcPlatform) << "Could not get plugin instance of" << file;
|
||||
qCWarning(dcPlatform) << "Could not get plugin instance of" << loader.fileName();
|
||||
loader.unload();
|
||||
return;
|
||||
}
|
||||
qCDebug(dcPlatform()) << "Loaded system plugin:" << file;
|
||||
qCDebug(dcPlatform()) << "Loaded system plugin:" << loader.fileName();
|
||||
m_platformSystemController->setParent(this);
|
||||
}
|
||||
|
||||
@ -125,17 +139,39 @@ void Platform::loadUpdatePlugin(const QString &file)
|
||||
loader.setFileName(file);
|
||||
loader.setLoadHints(QLibrary::ResolveAllSymbolsHint);
|
||||
if (!loader.load()) {
|
||||
qCWarning(dcPlatform) << "Could not load plugin data of" << file << "\n" << loader.errorString();
|
||||
qCWarning(dcPlatform) << loader.errorString();
|
||||
return;
|
||||
}
|
||||
m_platformUpdateController = qobject_cast<PlatformUpdateController*>(loader.instance());
|
||||
if (!m_platformUpdateController) {
|
||||
qCWarning(dcPlatform) << "Could not get plugin instance of" << file;
|
||||
qCWarning(dcPlatform) << "Could not get plugin instance of" << loader.fileName();
|
||||
loader.unload();
|
||||
return;
|
||||
}
|
||||
qCDebug(dcPlatform()) << "Loaded update plugin:" << file;
|
||||
qCDebug(dcPlatform()) << "Loaded update plugin:" << loader.fileName();
|
||||
m_platformUpdateController->setParent(this);
|
||||
}
|
||||
|
||||
void Platform::loadZeroConfPlugin(const QString &file)
|
||||
{
|
||||
if (m_platformZeroConfController) {
|
||||
return; // Not loading another...
|
||||
}
|
||||
QPluginLoader loader;
|
||||
loader.setFileName(file);
|
||||
loader.setLoadHints(QLibrary::ResolveAllSymbolsHint);
|
||||
if (!loader.load()) {
|
||||
qCWarning(dcPlatform) << loader.errorString();
|
||||
return;
|
||||
}
|
||||
m_platformZeroConfController = qobject_cast<PlatformZeroConfController*>(loader.instance());
|
||||
if (!m_platformZeroConfController) {
|
||||
qCWarning(dcPlatform) << "Could not get plugin instance of" << loader.fileName();
|
||||
loader.unload();
|
||||
return;
|
||||
}
|
||||
qCDebug(dcPlatform()) << "Loaded ZeroConf plugin:" << loader.fileName();
|
||||
m_platformZeroConfController->setParent(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
|
||||
class PlatformSystemController;
|
||||
class PlatformUpdateController;
|
||||
class PlatformZeroConfController;
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
@ -38,16 +39,19 @@ public:
|
||||
|
||||
PlatformSystemController *systemController() const;
|
||||
PlatformUpdateController *updateController() const;
|
||||
PlatformZeroConfController *zeroConfController() const;
|
||||
|
||||
private:
|
||||
QStringList pluginSearchDirs() const;
|
||||
|
||||
void loadSystemPlugin(const QString &file);
|
||||
void loadUpdatePlugin(const QString &file);
|
||||
void loadZeroConfPlugin(const QString &file);
|
||||
|
||||
private:
|
||||
PlatformSystemController *m_platformSystemController = nullptr;
|
||||
PlatformUpdateController *m_platformUpdateController = nullptr;
|
||||
PlatformZeroConfController *m_platformZeroConfController = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -37,6 +37,8 @@
|
||||
#include "nymeacore.h"
|
||||
#include "certificategenerator.h"
|
||||
#include "nymeasettings.h"
|
||||
#include "platform/platform.h"
|
||||
#include "platform/platformzeroconfcontroller.h"
|
||||
|
||||
#include "jsonrpc/jsonrpcserver.h"
|
||||
#include "servers/mocktcpserver.h"
|
||||
@ -47,6 +49,8 @@
|
||||
#include "servers/bluetoothserver.h"
|
||||
#include "servers/mqttbroker.h"
|
||||
|
||||
#include "network/zeroconf/zeroconfservicepublisher.h"
|
||||
|
||||
#include <QSslCertificate>
|
||||
#include <QSslConfiguration>
|
||||
#include <QSslKey>
|
||||
@ -54,8 +58,9 @@
|
||||
namespace nymeaserver {
|
||||
|
||||
/*! Constructs a \l{ServerManager} with the given \a configuration and \a parent. */
|
||||
ServerManager::ServerManager(NymeaConfiguration *configuration, QObject *parent) :
|
||||
ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configuration, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_platform(platform),
|
||||
m_sslConfiguration(QSslConfiguration())
|
||||
{
|
||||
if (!QSslSocket::supportsSsl()) {
|
||||
@ -108,14 +113,18 @@ ServerManager::ServerManager(NymeaConfiguration *configuration, QObject *parent)
|
||||
TcpServer *tcpServer = new TcpServer(config, m_sslConfiguration, this);
|
||||
m_jsonServer->registerTransportInterface(tcpServer, config.authenticationEnabled);
|
||||
m_tcpServers.insert(config.id, tcpServer);
|
||||
tcpServer->startServer();
|
||||
if (tcpServer->startServer()) {
|
||||
registerZeroConfService(config, "nymea-tcp", "_jsonrpc._tcp");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (const ServerConfiguration &config, configuration->webSocketServerConfigurations()) {
|
||||
WebSocketServer *webSocketServer = new WebSocketServer(config, m_sslConfiguration, this);
|
||||
m_jsonServer->registerTransportInterface(webSocketServer, config.authenticationEnabled);
|
||||
m_webSocketServers.insert(config.id, webSocketServer);
|
||||
webSocketServer->startServer();
|
||||
if (webSocketServer->startServer()) {
|
||||
registerZeroConfService(config, "nymea-ws", "_ws._tcp");
|
||||
}
|
||||
}
|
||||
|
||||
m_bluetoothServer = new BluetoothServer(this);
|
||||
@ -128,11 +137,16 @@ ServerManager::ServerManager(NymeaConfiguration *configuration, QObject *parent)
|
||||
WebServer *webServer = new WebServer(config, m_sslConfiguration, this);
|
||||
m_restServer->registerWebserver(webServer);
|
||||
m_webServers.insert(config.id, webServer);
|
||||
if (webServer->startServer()) {
|
||||
registerZeroConfService(config, "nymea-http", "_http._tcp");
|
||||
}
|
||||
}
|
||||
|
||||
m_mqttBroker = new MqttBroker(this);
|
||||
foreach (const ServerConfiguration &config, configuration->mqttServerConfigurations()) {
|
||||
m_mqttBroker->startServer(config);
|
||||
if (m_mqttBroker->startServer(config)) {
|
||||
registerZeroConfService(config, "nymea-mqtt", "_mqtt._tcp");
|
||||
}
|
||||
}
|
||||
m_mqttBroker->updatePolicies(configuration->mqttPolicies().values());
|
||||
|
||||
@ -183,6 +197,7 @@ void ServerManager::tcpServerConfigurationChanged(const QString &id)
|
||||
TcpServer *server = m_tcpServers.value(id);
|
||||
if (server) {
|
||||
qDebug(dcServerManager()) << "Restarting TCP server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
|
||||
unregisterZeroConfService(config.id);
|
||||
server->stopServer();
|
||||
server->setConfiguration(config);
|
||||
} else {
|
||||
@ -191,7 +206,9 @@ void ServerManager::tcpServerConfigurationChanged(const QString &id)
|
||||
m_tcpServers.insert(config.id, server);
|
||||
}
|
||||
m_jsonServer->registerTransportInterface(server, config.authenticationEnabled);
|
||||
server->startServer();
|
||||
if (server->startServer()) {
|
||||
registerZeroConfService(config, "nymea-tcp", "_jsonrpc._tcp");
|
||||
}
|
||||
}
|
||||
|
||||
void ServerManager::tcpServerConfigurationRemoved(const QString &id)
|
||||
@ -202,6 +219,7 @@ void ServerManager::tcpServerConfigurationRemoved(const QString &id)
|
||||
}
|
||||
TcpServer *server = m_tcpServers.take(id);
|
||||
m_jsonServer->unregisterTransportInterface(server);
|
||||
unregisterZeroConfService(id);
|
||||
server->stopServer();
|
||||
server->deleteLater();
|
||||
}
|
||||
@ -212,6 +230,7 @@ void ServerManager::webSocketServerConfigurationChanged(const QString &id)
|
||||
ServerConfiguration config = NymeaCore::instance()->configuration()->webSocketServerConfigurations().value(id);
|
||||
if (server) {
|
||||
qDebug(dcServerManager()) << "Restarting WebSocket server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
|
||||
unregisterZeroConfService(id);
|
||||
server->stopServer();
|
||||
server->setConfiguration(config);
|
||||
} else {
|
||||
@ -220,7 +239,9 @@ void ServerManager::webSocketServerConfigurationChanged(const QString &id)
|
||||
m_webSocketServers.insert(server->configuration().id, server);
|
||||
}
|
||||
m_jsonServer->registerTransportInterface(server, config.authenticationEnabled);
|
||||
server->startServer();
|
||||
if (server->startServer()) {
|
||||
registerZeroConfService(config, "nymea-ws", "_ws._tcp");
|
||||
}
|
||||
}
|
||||
|
||||
void ServerManager::webSocketServerConfigurationRemoved(const QString &id)
|
||||
@ -231,6 +252,7 @@ void ServerManager::webSocketServerConfigurationRemoved(const QString &id)
|
||||
}
|
||||
WebSocketServer *server = m_webSocketServers.take(id);
|
||||
m_jsonServer->unregisterTransportInterface(server);
|
||||
unregisterZeroConfService(id);
|
||||
server->stopServer();
|
||||
server->deleteLater();
|
||||
}
|
||||
@ -241,6 +263,7 @@ void ServerManager::webServerConfigurationChanged(const QString &id)
|
||||
WebServer *server = m_webServers.value(id);
|
||||
if (server) {
|
||||
qDebug(dcServerManager()) << "Restarting Web server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
|
||||
unregisterZeroConfService(id);
|
||||
server->stopServer();
|
||||
server->reconfigureServer(config);
|
||||
} else {
|
||||
@ -249,6 +272,9 @@ void ServerManager::webServerConfigurationChanged(const QString &id)
|
||||
m_restServer->registerWebserver(server);
|
||||
m_webServers.insert(config.id, server);
|
||||
}
|
||||
if (server->startServer()) {
|
||||
registerZeroConfService(config, "nymea-http", "_http._tcp");
|
||||
}
|
||||
}
|
||||
|
||||
void ServerManager::webServerConfigurationRemoved(const QString &id)
|
||||
@ -258,6 +284,7 @@ void ServerManager::webServerConfigurationRemoved(const QString &id)
|
||||
return;
|
||||
}
|
||||
WebServer *server = m_webServers.take(id);
|
||||
unregisterZeroConfService(id);
|
||||
server->stopServer();
|
||||
server->deleteLater();
|
||||
}
|
||||
@ -266,13 +293,18 @@ void ServerManager::mqttServerConfigurationChanged(const QString &id)
|
||||
{
|
||||
ServerConfiguration config = NymeaCore::instance()->configuration()->mqttServerConfigurations().value(id);
|
||||
if (m_mqttBroker->isRunning(id)) {
|
||||
unregisterZeroConfService(id);
|
||||
m_mqttBroker->stopServer(id);
|
||||
}
|
||||
m_mqttBroker->startServer(config, m_sslConfiguration);
|
||||
if (m_mqttBroker->startServer(config, m_sslConfiguration)) {
|
||||
registerZeroConfService(config, "nymea-mqtt", "_mqtt._tcp");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ServerManager::mqttServerConfigurationRemoved(const QString &id)
|
||||
{
|
||||
unregisterZeroConfService(id);
|
||||
m_mqttBroker->stopServer(id);
|
||||
}
|
||||
|
||||
@ -286,6 +318,29 @@ void ServerManager::mqttPolicyRemoved(const QString &clientId)
|
||||
m_mqttBroker->removePolicy(clientId);
|
||||
}
|
||||
|
||||
bool ServerManager::registerZeroConfService(const ServerConfiguration &configuration, const QString &namePrefix, const QString &serviceType)
|
||||
{
|
||||
// Note: reversed order
|
||||
QHash<QString, QString> txt;
|
||||
txt.insert("jsonrpcVersion", JSON_PROTOCOL_VERSION);
|
||||
txt.insert("serverVersion", NYMEA_VERSION_STRING);
|
||||
txt.insert("manufacturer", "guh GmbH");
|
||||
txt.insert("uuid", NymeaCore::instance()->configuration()->serverUuid().toString());
|
||||
txt.insert("name", NymeaCore::instance()->configuration()->serverName());
|
||||
txt.insert("sslEnabled", configuration.sslEnabled ? "true" : "false");
|
||||
QString name = namePrefix + "-" + configuration.id;
|
||||
if (!m_platform->zeroConfController()->zeroConfServicePublisher()->registerService(configuration.id, name, configuration.address, static_cast<quint16>(configuration.port), serviceType, txt)) {
|
||||
qCWarning(dcTcpServer()) << "Could not register ZeroConf service for" << configuration;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ServerManager::unregisterZeroConfService(const QString &configId)
|
||||
{
|
||||
m_platform->zeroConfController()->zeroConfServicePublisher()->unregisterService(configId);
|
||||
}
|
||||
|
||||
bool ServerManager::loadCertificate(const QString &certificateKeyFileName, const QString &certificateFileName)
|
||||
{
|
||||
QFile certificateKeyFile(certificateKeyFileName);
|
||||
|
||||
@ -33,6 +33,7 @@ class MockTcpServer;
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
class Platform;
|
||||
class NymeaConfiguration;
|
||||
class JsonRPCServer;
|
||||
class TcpServer;
|
||||
@ -46,7 +47,7 @@ class ServerManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ServerManager(NymeaConfiguration *configuration, QObject *parent = nullptr);
|
||||
explicit ServerManager(Platform *platform, NymeaConfiguration *configuration, QObject *parent = nullptr);
|
||||
|
||||
// Interfaces
|
||||
JsonRPCServer *jsonServer() const;
|
||||
@ -71,6 +72,12 @@ private slots:
|
||||
void mqttPolicyRemoved(const QString &clientId);
|
||||
|
||||
private:
|
||||
bool registerZeroConfService(const ServerConfiguration &configuration, const QString &namePrefix, const QString &serviceType);
|
||||
void unregisterZeroConfService(const QString &configId);
|
||||
|
||||
private:
|
||||
Platform *m_platform = nullptr;
|
||||
|
||||
// Interfaces
|
||||
JsonRPCServer *m_jsonServer;
|
||||
RestServer *m_restServer;
|
||||
|
||||
@ -63,7 +63,6 @@ void RestServer::registerWebserver(WebServer *webServer)
|
||||
connect(webServer, &WebServer::clientConnected, this, &RestServer::clientConnected);
|
||||
connect(webServer, &WebServer::clientDisconnected, this, &RestServer::clientDisconnected);
|
||||
connect(webServer, &WebServer::httpRequestReady, this, &RestServer::processHttpRequest);
|
||||
QMetaObject::invokeMethod(webServer, "startServer", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void RestServer::setup()
|
||||
|
||||
@ -80,8 +80,6 @@ TcpServer::TcpServer(const ServerConfiguration &configuration, const QSslConfigu
|
||||
m_server(nullptr),
|
||||
m_sslConfig(sslConfiguration)
|
||||
{
|
||||
m_avahiService = new QtAvahiService(this);
|
||||
connect(m_avahiService, &QtAvahiService::serviceStateChanged, this, &TcpServer::onAvahiServiceStateChanged);
|
||||
}
|
||||
|
||||
/*! Destructor of this \l{TcpServer}. */
|
||||
@ -155,29 +153,6 @@ void TcpServer::onDataAvailable(QSslSocket * socket, const QByteArray &data)
|
||||
emit dataAvailable(clientId, data);
|
||||
}
|
||||
|
||||
void TcpServer::onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state)
|
||||
{
|
||||
Q_UNUSED(state)
|
||||
}
|
||||
|
||||
void TcpServer::resetAvahiService()
|
||||
{
|
||||
if (m_avahiService)
|
||||
m_avahiService->resetService();
|
||||
|
||||
// Note: reversed order
|
||||
QHash<QString, QString> txt;
|
||||
txt.insert("jsonrpcVersion", JSON_PROTOCOL_VERSION);
|
||||
txt.insert("serverVersion", NYMEA_VERSION_STRING);
|
||||
txt.insert("manufacturer", "guh GmbH");
|
||||
txt.insert("uuid", NymeaCore::instance()->configuration()->serverUuid().toString());
|
||||
txt.insert("name", NymeaCore::instance()->configuration()->serverName());
|
||||
txt.insert("sslEnabled", configuration().sslEnabled ? "true" : "false");
|
||||
if (!m_avahiService->registerService(QString("nymea-tcp-%1").arg(configuration().id), configuration().address, static_cast<quint16>(configuration().port), "_jsonrpc._tcp", txt)) {
|
||||
qCWarning(dcTcpServer()) << "Could not register avahi service for" << configuration();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! Returns true if this \l{TcpServer} could be reconfigured with the given \a config. */
|
||||
void TcpServer::reconfigureServer(const ServerConfiguration &config)
|
||||
@ -198,7 +173,6 @@ void TcpServer::reconfigureServer(const ServerConfiguration &config)
|
||||
void TcpServer::setServerName(const QString &serverName)
|
||||
{
|
||||
m_serverName = serverName;
|
||||
resetAvahiService();
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{TcpServer} started successfully.
|
||||
@ -220,7 +194,6 @@ bool TcpServer::startServer()
|
||||
connect(m_server, &SslServer::dataAvailable, this, &TcpServer::onDataAvailable);
|
||||
|
||||
qCDebug(dcTcpServer()) << "Started Tcp server" << serverUrl().toString();
|
||||
resetAvahiService();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -231,9 +204,6 @@ bool TcpServer::startServer()
|
||||
*/
|
||||
bool TcpServer::stopServer()
|
||||
{
|
||||
if (m_avahiService)
|
||||
m_avahiService->resetService();
|
||||
|
||||
if (!m_server)
|
||||
return true;
|
||||
|
||||
|
||||
@ -32,7 +32,6 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "transportinterface.h"
|
||||
#include "hardware/network/avahi/qtavahiservice.h"
|
||||
|
||||
#include "loggingcategories.h"
|
||||
|
||||
@ -84,8 +83,6 @@ public:
|
||||
private:
|
||||
QTimer *m_timer;
|
||||
|
||||
QtAvahiService *m_avahiService;
|
||||
|
||||
SslServer * m_server;
|
||||
QHash<QUuid, QTcpSocket *> m_clientList;
|
||||
|
||||
@ -97,9 +94,6 @@ private slots:
|
||||
void onDataAvailable(QSslSocket *socket, const QByteArray &data);
|
||||
void onError(QAbstractSocket::SocketError error);
|
||||
|
||||
void onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state);
|
||||
void resetAvahiService();
|
||||
|
||||
public slots:
|
||||
void reconfigureServer(const ServerConfiguration &configuration);
|
||||
void setServerName(const QString &serverName) override;
|
||||
|
||||
@ -106,9 +106,6 @@ WebServer::WebServer(const WebServerConfiguration &configuration, const QSslConf
|
||||
m_configuration.publicFolder = QCoreApplication::applicationDirPath();
|
||||
}
|
||||
qCDebug(dcWebServer()) << "Starting WebServer. Interface:" << m_configuration.address << "Port:" << m_configuration.port << "SSL:" << m_configuration.sslEnabled << "AUTH:" << m_configuration.authenticationEnabled << "Public folder:" << QDir(m_configuration.publicFolder).canonicalPath();
|
||||
|
||||
m_avahiService = new QtAvahiService(this);
|
||||
connect(m_avahiService, &QtAvahiService::serviceStateChanged, this, &WebServer::onAvahiServiceStateChanged);
|
||||
}
|
||||
|
||||
/*! Destructor of this \l{WebServer}. */
|
||||
@ -553,32 +550,6 @@ void WebServer::onAsyncReplyFinished()
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void WebServer::onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state)
|
||||
{
|
||||
Q_UNUSED(state)
|
||||
}
|
||||
|
||||
void WebServer::resetAvahiService()
|
||||
{
|
||||
if (!m_avahiService)
|
||||
return;
|
||||
|
||||
m_avahiService->resetService();
|
||||
|
||||
// Note: reversed order
|
||||
QHash<QString, QString> txt;
|
||||
txt.insert("jsonrpcVersion", JSON_PROTOCOL_VERSION);
|
||||
txt.insert("serverVersion", NYMEA_VERSION_STRING);
|
||||
txt.insert("manufacturer", "guh GmbH");
|
||||
txt.insert("uuid", NymeaCore::instance()->configuration()->serverUuid().toString());
|
||||
txt.insert("name", NymeaCore::instance()->configuration()->serverName());
|
||||
txt.insert("sslEnabled", m_configuration.sslEnabled ? "true" : "false");
|
||||
|
||||
if (!m_avahiService->registerService(QString("nymea-http-%1").arg(m_configuration.id), m_configuration.address, static_cast<quint16>(m_configuration.port), "_http._tcp", txt)) {
|
||||
qCWarning(dcTcpServer()) << "Could not register avahi service for" << m_configuration;
|
||||
}
|
||||
}
|
||||
|
||||
/*! Set the configuration of this \l{WebServer} to the given \a config.
|
||||
*
|
||||
* \sa WebServerConfiguration
|
||||
@ -602,7 +573,6 @@ void WebServer::reconfigureServer(const WebServerConfiguration &config)
|
||||
void WebServer::setServerName(const QString &serverName)
|
||||
{
|
||||
m_serverName = serverName;
|
||||
resetAvahiService();
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{WebServer} started successfully. */
|
||||
@ -615,7 +585,6 @@ bool WebServer::startServer()
|
||||
}
|
||||
|
||||
qCDebug(dcWebServer()) << "Started web server on" << serverUrl().toString();
|
||||
resetAvahiService();
|
||||
|
||||
m_enabled = true;
|
||||
return true;
|
||||
@ -624,9 +593,6 @@ bool WebServer::startServer()
|
||||
/*! Returns true if this \l{WebServer} stopped successfully. */
|
||||
bool WebServer::stopServer()
|
||||
{
|
||||
if (m_avahiService)
|
||||
m_avahiService->resetService();
|
||||
|
||||
foreach (QSslSocket *client, m_clientList.values())
|
||||
client->close();
|
||||
|
||||
|
||||
@ -36,8 +36,6 @@
|
||||
|
||||
#include "nymeaconfiguration.h"
|
||||
|
||||
#include "hardware/network/avahi/qtavahiservice.h"
|
||||
|
||||
// Note: Hypertext Transfer Protocol (HTTP/1.1) from the Internet Engineering Task Force (IETF):
|
||||
// https://tools.ietf.org/html/rfc7231
|
||||
|
||||
@ -86,7 +84,6 @@ private:
|
||||
QList<WebServerClient *> m_webServerClients;
|
||||
QHash<QSslSocket *, HttpRequest> m_incompleteRequests;
|
||||
|
||||
QtAvahiService *m_avahiService = nullptr;
|
||||
QString m_serverName;
|
||||
WebServerConfiguration m_configuration;
|
||||
QSslConfiguration m_sslConfiguration;
|
||||
@ -115,9 +112,6 @@ private slots:
|
||||
void onError(QAbstractSocket::SocketError error);
|
||||
void onAsyncReplyFinished();
|
||||
|
||||
void onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state);
|
||||
void resetAvahiService();
|
||||
|
||||
public slots:
|
||||
void reconfigureServer(const WebServerConfiguration &config);
|
||||
void setServerName(const QString &serverName);
|
||||
|
||||
@ -65,8 +65,6 @@ WebSocketServer::WebSocketServer(const ServerConfiguration &configuration, const
|
||||
m_sslConfiguration(sslConfiguration),
|
||||
m_enabled(false)
|
||||
{
|
||||
m_avahiService = new QtAvahiService(this);
|
||||
connect(m_avahiService, &QtAvahiService::serviceStateChanged, this, &WebSocketServer::onAvahiServiceStateChanged);
|
||||
}
|
||||
|
||||
/*! Destructor of this \l{WebSocketServer}. */
|
||||
@ -117,19 +115,6 @@ void WebSocketServer::terminateClientConnection(const QUuid &clientId)
|
||||
}
|
||||
}
|
||||
|
||||
QHash<QString, QString> WebSocketServer::createTxtRecord()
|
||||
{
|
||||
// Note: reversed order
|
||||
QHash<QString, QString> txt;
|
||||
txt.insert("jsonrpcVersion", JSON_PROTOCOL_VERSION);
|
||||
txt.insert("serverVersion", NYMEA_VERSION_STRING);
|
||||
txt.insert("manufacturer", "guh GmbH");
|
||||
txt.insert("uuid", NymeaCore::instance()->configuration()->serverUuid().toString());
|
||||
txt.insert("name", NymeaCore::instance()->configuration()->serverName());
|
||||
txt.insert("sslEnabled", configuration().sslEnabled ? "true" : "false");
|
||||
return txt;
|
||||
}
|
||||
|
||||
void WebSocketServer::onClientConnected()
|
||||
{
|
||||
// got a new client connected
|
||||
@ -202,21 +187,6 @@ void WebSocketServer::onPing(quint64 elapsedTime, const QByteArray &payload)
|
||||
qCDebug(dcWebSocketServer) << "Ping response from" << clientId.toString() << elapsedTime << payload;
|
||||
}
|
||||
|
||||
void WebSocketServer::onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state)
|
||||
{
|
||||
Q_UNUSED(state)
|
||||
}
|
||||
|
||||
void WebSocketServer::resetAvahiService()
|
||||
{
|
||||
if (!m_avahiService)
|
||||
return;
|
||||
|
||||
m_avahiService->resetService();
|
||||
if (!m_avahiService->registerService(QString("nymea-ws-%1").arg(configuration().id), configuration().address, static_cast<quint16>(configuration().port), "_ws._tcp", createTxtRecord())) {
|
||||
qCWarning(dcWebSocketServer()) << "Could not register avahi service for" << configuration();
|
||||
}
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{WebSocketServer} could be reconfigured with the given \a config. */
|
||||
void WebSocketServer::reconfigureServer(const ServerConfiguration &config)
|
||||
@ -240,7 +210,6 @@ void WebSocketServer::reconfigureServer(const ServerConfiguration &config)
|
||||
void WebSocketServer::setServerName(const QString &serverName)
|
||||
{
|
||||
m_serverName = serverName;
|
||||
resetAvahiService();
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{WebSocketServer} started successfully.
|
||||
@ -264,7 +233,6 @@ bool WebSocketServer::startServer()
|
||||
}
|
||||
|
||||
qCDebug(dcWebSocketServer()) << "Server started on" << serverUrl().toString();
|
||||
resetAvahiService();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -274,9 +242,6 @@ bool WebSocketServer::startServer()
|
||||
*/
|
||||
bool WebSocketServer::stopServer()
|
||||
{
|
||||
if (m_avahiService)
|
||||
m_avahiService->resetService();
|
||||
|
||||
foreach (QWebSocket *client, m_clientList.values()) {
|
||||
client->close(QWebSocketProtocol::CloseCodeNormal, "Stop server");
|
||||
}
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
#include <QWebSocket>
|
||||
#include <QWebSocketServer>
|
||||
|
||||
#include "hardware/network/avahi/qtavahiservice.h"
|
||||
#include "transportinterface.h"
|
||||
|
||||
// Note: WebSocket Protocol from the Internet Engineering Task Force (IETF) -> RFC6455 V13:
|
||||
@ -55,12 +54,9 @@ public:
|
||||
private:
|
||||
QWebSocketServer *m_server = nullptr;
|
||||
QHash<QUuid, QWebSocket *> m_clientList;
|
||||
QtAvahiService *m_avahiService = nullptr;
|
||||
QSslConfiguration m_sslConfiguration;
|
||||
bool m_enabled;
|
||||
|
||||
QHash<QString, QString> createTxtRecord();
|
||||
|
||||
private slots:
|
||||
void onClientConnected();
|
||||
void onClientDisconnected();
|
||||
@ -70,9 +66,6 @@ private slots:
|
||||
void onServerError(QAbstractSocket::SocketError error);
|
||||
void onPing(quint64 elapsedTime, const QByteArray & payload);
|
||||
|
||||
void onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state);
|
||||
void resetAvahiService();
|
||||
|
||||
public slots:
|
||||
void reconfigureServer(const ServerConfiguration &config);
|
||||
void setServerName(const QString &serverName) override;
|
||||
|
||||
@ -30,7 +30,7 @@ class UpnpDiscovery;
|
||||
class PluginTimerManager;
|
||||
class NetworkAccessManager;
|
||||
class UpnpDeviceDescriptor;
|
||||
class QtAvahiServiceBrowser;
|
||||
class ZeroConfServiceBrowser;
|
||||
class BluetoothLowEnergyManager;
|
||||
class MqttProvider;
|
||||
class HardwareResource;
|
||||
@ -47,7 +47,7 @@ public:
|
||||
virtual PluginTimerManager *pluginTimerManager() = 0;
|
||||
virtual NetworkAccessManager *networkManager() = 0;
|
||||
virtual UpnpDiscovery *upnpDiscovery() = 0;
|
||||
virtual QtAvahiServiceBrowser *avahiBrowser() = 0;
|
||||
virtual ZeroConfServiceBrowser *zeroConfServiceBrowser() = 0;
|
||||
virtual BluetoothLowEnergyManager *bluetoothLowEnergyManager() = 0;
|
||||
virtual MqttProvider *mqttProvider() = 0;
|
||||
|
||||
|
||||
@ -8,8 +8,6 @@ DEFINES += LIBNYMEA_LIBRARY
|
||||
|
||||
QMAKE_LFLAGS += -fPIC
|
||||
|
||||
LIBS += -lavahi-common -lavahi-client
|
||||
|
||||
HEADERS += devicemanager.h \
|
||||
libnymea.h \
|
||||
platform/package.h \
|
||||
@ -31,8 +29,9 @@ HEADERS += devicemanager.h \
|
||||
network/upnp/upnpdiscoveryreply.h \
|
||||
network/networkaccessmanager.h \
|
||||
network/oauth2.h \
|
||||
network/avahi/qtavahiservicebrowser.h \
|
||||
network/avahi/avahiserviceentry.h \
|
||||
network/zeroconf/zeroconfservicebrowser.h \
|
||||
network/zeroconf/zeroconfserviceentry.h \
|
||||
network/zeroconf/zeroconfservicepublisher.h \
|
||||
hardware/bluetoothlowenergy/bluetoothlowenergydevice.h \
|
||||
hardware/bluetoothlowenergy/bluetoothdiscoveryreply.h \
|
||||
hardware/bluetoothlowenergy/bluetoothlowenergymanager.h \
|
||||
@ -69,7 +68,8 @@ HEADERS += devicemanager.h \
|
||||
network/mqtt/mqttchannel.h \
|
||||
translator.h \
|
||||
platform/platformsystemcontroller.h \
|
||||
platform/platformupdatecontroller.h
|
||||
platform/platformupdatecontroller.h \
|
||||
platform/platformzeroconfcontroller.h \
|
||||
|
||||
SOURCES += devicemanager.cpp \
|
||||
loggingcategories.cpp \
|
||||
@ -90,8 +90,9 @@ SOURCES += devicemanager.cpp \
|
||||
network/upnp/upnpdiscoveryreply.cpp \
|
||||
network/networkaccessmanager.cpp \
|
||||
network/oauth2.cpp \
|
||||
network/avahi/avahiserviceentry.cpp \
|
||||
network/avahi/qtavahiservicebrowser.cpp \
|
||||
network/zeroconf/zeroconfserviceentry.cpp \
|
||||
network/zeroconf/zeroconfservicebrowser.cpp \
|
||||
network/zeroconf/zeroconfservicepublisher.cpp \
|
||||
hardware/bluetoothlowenergy/bluetoothlowenergymanager.cpp \
|
||||
hardware/bluetoothlowenergy/bluetoothlowenergydevice.cpp \
|
||||
hardware/bluetoothlowenergy/bluetoothdiscoveryreply.cpp \
|
||||
@ -128,7 +129,8 @@ SOURCES += devicemanager.cpp \
|
||||
network/mqtt/mqttchannel.cpp \
|
||||
translator.cpp \
|
||||
platform/platformsystemcontroller.cpp \
|
||||
platform/platformupdatecontroller.cpp
|
||||
platform/platformupdatecontroller.cpp \
|
||||
platform/platformzeroconfcontroller.cpp \
|
||||
|
||||
|
||||
RESOURCES += \
|
||||
|
||||
@ -27,6 +27,7 @@ Q_LOGGING_CATEGORY(dcDeviceManager, "DeviceManager")
|
||||
Q_LOGGING_CATEGORY(dcSystem, "System")
|
||||
Q_LOGGING_CATEGORY(dcPlatform, "Platform")
|
||||
Q_LOGGING_CATEGORY(dcPlatformUpdate, "PlatformUpdate")
|
||||
Q_LOGGING_CATEGORY(dcPlatformZeroConf, "PlatformZeroConf")
|
||||
Q_LOGGING_CATEGORY(dcTimeManager, "TimeManager")
|
||||
Q_LOGGING_CATEGORY(dcRuleEngine, "RuleEngine")
|
||||
Q_LOGGING_CATEGORY(dcRuleEngineDebug, "RuleEngineDebug")
|
||||
@ -44,8 +45,6 @@ Q_LOGGING_CATEGORY(dcJsonRpc, "JsonRpc")
|
||||
Q_LOGGING_CATEGORY(dcJsonRpcTraffic, "JsonRpcTraffic")
|
||||
Q_LOGGING_CATEGORY(dcRest, "Rest")
|
||||
Q_LOGGING_CATEGORY(dcOAuth2, "OAuth2")
|
||||
Q_LOGGING_CATEGORY(dcAvahi, "Avahi")
|
||||
Q_LOGGING_CATEGORY(dcAvahiDebug, "AvahiDebug")
|
||||
Q_LOGGING_CATEGORY(dcUpnp, "UPnP")
|
||||
Q_LOGGING_CATEGORY(dcBluetooth, "Bluetooth")
|
||||
Q_LOGGING_CATEGORY(dcCloud, "Cloud")
|
||||
|
||||
@ -32,6 +32,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcDeviceManager)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcSystem)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcPlatform)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcPlatformUpdate)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcPlatformZeroConf)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcTimeManager)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcRuleEngine)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcRuleEngineDebug)
|
||||
@ -49,8 +50,6 @@ Q_DECLARE_LOGGING_CATEGORY(dcJsonRpc)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcJsonRpcTraffic)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcRest)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcOAuth2)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcAvahi)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcAvahiDebug)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcUpnp)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcBluetooth)
|
||||
Q_DECLARE_LOGGING_CATEGORY(dcCloud)
|
||||
|
||||
@ -21,13 +21,13 @@
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/*!
|
||||
\class QtAvahiServiceBrowser
|
||||
\class ZeroConfServiceBrowser
|
||||
\brief Allows to browse avahi services in the local network.
|
||||
|
||||
\ingroup hardware
|
||||
\inmodule libnymea
|
||||
|
||||
The QtAvahiServiceBrowser allows to discover the avahi network and get services.
|
||||
The ZeroConfServiceBrowser allows to discover the avahi network and get services.
|
||||
|
||||
|
||||
\chapter Example
|
||||
@ -37,7 +37,7 @@
|
||||
\tt devicepluginexample.h
|
||||
|
||||
\code
|
||||
#include "network/avahi/avahiserviceentry.h"
|
||||
#include "network/avahi/ZeroConfServiceEntry.h"
|
||||
|
||||
class DevicePluginExample : public DevicePlugin
|
||||
{
|
||||
@ -47,8 +47,8 @@
|
||||
void init() override;
|
||||
|
||||
private slots:
|
||||
void onServiceEntryAdded(const AvahiServiceEntry &serviceEntry);
|
||||
void onServiceEntryRemoved(const AvahiServiceEntry &serviceEntry);
|
||||
void onServiceEntryAdded(const ZeroConfServiceEntry &serviceEntry);
|
||||
void onServiceEntryRemoved(const ZeroConfServiceEntry &serviceEntry);
|
||||
|
||||
...
|
||||
|
||||
@ -60,17 +60,17 @@
|
||||
\code
|
||||
|
||||
void DevicePluginExample::init() {
|
||||
connect(hardwareManager()->avahiBrowser(), &QtAvahiServiceBrowser::serviceEntryAdded, this, &DevicePluginExample::onServiceEntryAdded);
|
||||
connect(hardwareManager()->avahiBrowser(), &QtAvahiServiceBrowser::serviceEntryRemoved, this, &DevicePluginExample::onServiceEntryRemoved);
|
||||
connect(hardwareManager()->avahiBrowser(), &ZeroConfServiceBrowser::serviceEntryAdded, this, &DevicePluginExample::onServiceEntryAdded);
|
||||
connect(hardwareManager()->avahiBrowser(), &ZeroConfServiceBrowser::serviceEntryRemoved, this, &DevicePluginExample::onServiceEntryRemoved);
|
||||
}
|
||||
|
||||
void DevicePluginExample::onServiceEntryAdded(const AvahiServiceEntry &serviceEntry) {
|
||||
void DevicePluginExample::onServiceEntryAdded(const ZeroConfServiceEntry &serviceEntry) {
|
||||
qCDebug(dcExample()) << "New service added to network:" << serviceEntry;
|
||||
|
||||
...
|
||||
}
|
||||
|
||||
void DevicePluginExample::onServiceEntryRemoved(const AvahiServiceEntry &serviceEntry) {
|
||||
void DevicePluginExample::onServiceEntryRemoved(const ZeroConfServiceEntry &serviceEntry) {
|
||||
qCDebug(dcExample()) << "Service removed from network:" << serviceEntry;
|
||||
|
||||
...
|
||||
@ -78,34 +78,54 @@
|
||||
|
||||
\endcode
|
||||
|
||||
\sa AvahiServiceEntry
|
||||
\sa ZeroConfServiceEntry
|
||||
|
||||
*/
|
||||
|
||||
/*! \fn QtAvahiServiceBrowser::~QtAvahiServiceBrowser();
|
||||
Destroys this QtAvahiServiceBrowser;
|
||||
/*! \fn ZeroConfServiceBrowser::~ZeroConfServiceBrowser();
|
||||
Destroys this ZeroConfServiceBrowser;
|
||||
*/
|
||||
|
||||
/*! \fn QList<AvahiServiceEntry> QtAvahiServiceBrowser::serviceEntries() const;
|
||||
/*! \fn QList<ZeroConfServiceEntry> ZeroConfServiceBrowser::serviceEntries() const;
|
||||
Returns the list of available service entries in the network of this browser.
|
||||
*/
|
||||
|
||||
// Signals
|
||||
/*! \fn void QtAvahiServiceBrowser::serviceEntryAdded(const AvahiServiceEntry &entry);
|
||||
/*! \fn void ZeroConfServiceBrowser::serviceEntryAdded(const ZeroConfServiceEntry &entry);
|
||||
This signal will be emitted when a new \a entry was added to the current entry list.
|
||||
*/
|
||||
|
||||
/*! \fn void QtAvahiServiceBrowser::serviceEntryRemoved(const AvahiServiceEntry &entry);
|
||||
/*! \fn void ZeroConfServiceBrowser::serviceEntryRemoved(const ZeroConfServiceEntry &entry);
|
||||
This signal will be emitted when a new \a entry was removed from the current entry list.
|
||||
*/
|
||||
|
||||
#include "qtavahiservicebrowser.h"
|
||||
#include "zeroconfservicebrowser.h"
|
||||
|
||||
/*! Constructs a new \l{QtAvahiServiceBrowser} with the given \a parent. */
|
||||
QtAvahiServiceBrowser::QtAvahiServiceBrowser(QObject *parent) :
|
||||
HardwareResource("Avahi service browser", parent)
|
||||
/*! Constructs a new \l{ZeroConfServiceBrowser} with the given \a parent. */
|
||||
ZeroConfServiceBrowser::ZeroConfServiceBrowser(QObject *parent) :
|
||||
HardwareResource("ZeroConf service browser", parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool ZeroConfServiceBrowser::available() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ZeroConfServiceBrowser::enabled() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void ZeroConfServiceBrowser::setEnabled(bool enabled)
|
||||
{
|
||||
Q_UNUSED(enabled)
|
||||
}
|
||||
|
||||
QList<ZeroConfServiceEntry> ZeroConfServiceBrowser::serviceEntries() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@ -20,30 +20,34 @@
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef QTAVAHISERVICEBROWSER_H
|
||||
#define QTAVAHISERVICEBROWSER_H
|
||||
#ifndef ZEROCONFSERVICEBROWSER_H
|
||||
#define ZEROCONFSERVICEBROWSER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <avahi-client/lookup.h>
|
||||
|
||||
#include "libnymea.h"
|
||||
#include "hardwareresource.h"
|
||||
#include "avahiserviceentry.h"
|
||||
#include "zeroconfserviceentry.h"
|
||||
|
||||
class LIBNYMEA_EXPORT QtAvahiServiceBrowser : public HardwareResource
|
||||
class LIBNYMEA_EXPORT ZeroConfServiceBrowser : public HardwareResource
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QtAvahiServiceBrowser(QObject *parent = nullptr);
|
||||
virtual ~QtAvahiServiceBrowser() = default;
|
||||
explicit ZeroConfServiceBrowser(QObject *parent = nullptr);
|
||||
virtual ~ZeroConfServiceBrowser() = default;
|
||||
|
||||
virtual QList<AvahiServiceEntry> serviceEntries() const = 0;
|
||||
virtual bool available() const override;
|
||||
virtual bool enabled() const override;
|
||||
virtual void setEnabled(bool enabled) override;
|
||||
|
||||
|
||||
virtual QList<ZeroConfServiceEntry> serviceEntries() const;
|
||||
|
||||
signals:
|
||||
void serviceEntryAdded(const AvahiServiceEntry &entry);
|
||||
void serviceEntryRemoved(const AvahiServiceEntry &entry);
|
||||
void serviceEntryAdded(const ZeroConfServiceEntry &entry);
|
||||
void serviceEntryRemoved(const ZeroConfServiceEntry &entry);
|
||||
|
||||
};
|
||||
|
||||
#endif // QTAVAHISERVICEBROWSER_H
|
||||
#endif // ZEROCONFSERVICEBROWSER_H
|
||||
@ -21,7 +21,7 @@
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/*!
|
||||
\class AvahiServiceEntry
|
||||
\class ZeroConfServiceEntry
|
||||
\brief Holds information about an avahi service entry.
|
||||
|
||||
\ingroup types
|
||||
@ -31,19 +31,18 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "avahiserviceentry.h"
|
||||
#include "zeroconfserviceentry.h"
|
||||
|
||||
/*! Constructs an empty invalid \l{AvahiServiceEntry}*/
|
||||
AvahiServiceEntry::AvahiServiceEntry() :
|
||||
/*! Constructs an empty invalid \l{ZeroConfServiceEntry}*/
|
||||
ZeroConfServiceEntry::ZeroConfServiceEntry() :
|
||||
m_port(0),
|
||||
m_protocol(QAbstractSocket::UnknownNetworkLayerProtocol)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*! Constructs a new \l{AvahiServiceEntry} with the given \a name, \a serviceType, \a hostAddress, \a domain, \a hostName, \a port, \a protocol, \a txt and \a flags.*/
|
||||
AvahiServiceEntry::AvahiServiceEntry(QString name, QString serviceType, QHostAddress hostAddress, QString domain, QString hostName, quint16 port, QAbstractSocket::NetworkLayerProtocol protocol, QStringList txt, AvahiLookupResultFlags flags) :
|
||||
/*! Constructs a new \l{ZeroConfServiceEntry} with the given \a name, \a serviceType, \a hostAddress, \a domain, \a hostName, \a port, \a protocol, \a txt and flags.*/
|
||||
ZeroConfServiceEntry::ZeroConfServiceEntry(QString name, QString serviceType, QHostAddress hostAddress, QString domain, QString hostName, quint16 port, QAbstractSocket::NetworkLayerProtocol protocol, QStringList txt, bool cached, bool isWideArea, bool isMulticast, bool isLocal, bool isOurOwn):
|
||||
m_name(name),
|
||||
m_serviceType(serviceType),
|
||||
m_hostAddress(hostAddress),
|
||||
@ -52,103 +51,101 @@ AvahiServiceEntry::AvahiServiceEntry(QString name, QString serviceType, QHostAdd
|
||||
m_port(port),
|
||||
m_protocol(protocol),
|
||||
m_txt(txt),
|
||||
m_flags(flags)
|
||||
m_isCached(cached),
|
||||
m_isWideArea(isWideArea),
|
||||
m_isMulticast(isMulticast),
|
||||
m_isLocal(isLocal),
|
||||
m_isOurOwn(isOurOwn)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*! Returns the name of this \l{AvahiServiceEntry}.*/
|
||||
QString AvahiServiceEntry::name() const
|
||||
/*! Returns the name of this \l{ZeroConfServiceEntry}.*/
|
||||
QString ZeroConfServiceEntry::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/*! Returns the service type of this \l{AvahiServiceEntry}.*/
|
||||
QString AvahiServiceEntry::serviceType() const
|
||||
/*! Returns the service type of this \l{ZeroConfServiceEntry}.*/
|
||||
QString ZeroConfServiceEntry::serviceType() const
|
||||
{
|
||||
return m_serviceType;
|
||||
}
|
||||
|
||||
/*! Returns the host address of this \l{AvahiServiceEntry}.*/
|
||||
QHostAddress AvahiServiceEntry::hostAddress() const
|
||||
/*! Returns the host address of this \l{ZeroConfServiceEntry}.*/
|
||||
QHostAddress ZeroConfServiceEntry::hostAddress() const
|
||||
{
|
||||
return m_hostAddress;
|
||||
}
|
||||
|
||||
/*! Returns the domain of this \l{AvahiServiceEntry}.*/
|
||||
QString AvahiServiceEntry::domain() const
|
||||
/*! Returns the domain of this \l{ZeroConfServiceEntry}.*/
|
||||
QString ZeroConfServiceEntry::domain() const
|
||||
{
|
||||
return m_domain;
|
||||
}
|
||||
|
||||
/*! Returns the host name of this \l{AvahiServiceEntry}.*/
|
||||
QString AvahiServiceEntry::hostName() const
|
||||
/*! Returns the host name of this \l{ZeroConfServiceEntry}.*/
|
||||
QString ZeroConfServiceEntry::hostName() const
|
||||
{
|
||||
return m_hostName;
|
||||
}
|
||||
|
||||
/*! Returns the port of this \l{AvahiServiceEntry}.*/
|
||||
quint16 AvahiServiceEntry::port() const
|
||||
/*! Returns the port of this \l{ZeroConfServiceEntry}.*/
|
||||
quint16 ZeroConfServiceEntry::port() const
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
/*! Returns the network protocol of this \l{AvahiServiceEntry}.*/
|
||||
QAbstractSocket::NetworkLayerProtocol AvahiServiceEntry::protocol() const
|
||||
/*! Returns the network protocol of this \l{ZeroConfServiceEntry}.*/
|
||||
QAbstractSocket::NetworkLayerProtocol ZeroConfServiceEntry::protocol() const
|
||||
{
|
||||
return m_protocol;
|
||||
}
|
||||
|
||||
/*! Returns the avahi flags of this \l{AvahiServiceEntry}.*/
|
||||
AvahiLookupResultFlags AvahiServiceEntry::flags() const
|
||||
{
|
||||
return m_flags;
|
||||
}
|
||||
|
||||
/*! Returns the txt string list of this \l{AvahiServiceEntry}.*/
|
||||
QStringList AvahiServiceEntry::txt() const
|
||||
/*! Returns the txt string list of this \l{ZeroConfServiceEntry}.*/
|
||||
QStringList ZeroConfServiceEntry::txt() const
|
||||
{
|
||||
return m_txt;
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{AvahiServiceEntry} is valid.*/
|
||||
bool AvahiServiceEntry::isValid() const
|
||||
/*! Returns true if this \l{ZeroConfServiceEntry} is valid.*/
|
||||
bool ZeroConfServiceEntry::isValid() const
|
||||
{
|
||||
return !m_hostAddress.isNull() && !m_hostName.isEmpty() && m_port != 0 && m_protocol != QAbstractSocket::UnknownNetworkLayerProtocol;
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{AvahiServiceEntry} is cached.*/
|
||||
bool AvahiServiceEntry::isChached() const
|
||||
/*! Returns true if this \l{ZeroConfServiceEntry} is cached.*/
|
||||
bool ZeroConfServiceEntry::isChached() const
|
||||
{
|
||||
return m_flags & AVAHI_LOOKUP_RESULT_CACHED;
|
||||
return m_isCached;
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{AvahiServiceEntry} was found in the wide area.*/
|
||||
bool AvahiServiceEntry::isWideArea() const
|
||||
/*! Returns true if this \l{ZeroConfServiceEntry} was found in the wide area.*/
|
||||
bool ZeroConfServiceEntry::isWideArea() const
|
||||
{
|
||||
return m_flags & AVAHI_LOOKUP_RESULT_WIDE_AREA;
|
||||
return m_isWideArea;
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{AvahiServiceEntry} is a multicast service.*/
|
||||
bool AvahiServiceEntry::isMulticast() const
|
||||
/*! Returns true if this \l{ZeroConfServiceEntry} is a multicast service.*/
|
||||
bool ZeroConfServiceEntry::isMulticast() const
|
||||
{
|
||||
return m_flags & AVAHI_LOOKUP_RESULT_MULTICAST;
|
||||
return m_isMulticast;
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{AvahiServiceEntry} was found local.*/
|
||||
bool AvahiServiceEntry::isLocal() const
|
||||
/*! Returns true if this \l{ZeroConfServiceEntry} was found local.*/
|
||||
bool ZeroConfServiceEntry::isLocal() const
|
||||
{
|
||||
return m_flags & AVAHI_LOOKUP_RESULT_LOCAL;
|
||||
return m_isLocal;
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{AvahiServiceEntry} is our own service.*/
|
||||
bool AvahiServiceEntry::isOurOwn() const
|
||||
/*! Returns true if this \l{ZeroConfServiceEntry} is our own service.*/
|
||||
bool ZeroConfServiceEntry::isOurOwn() const
|
||||
{
|
||||
return m_flags & AVAHI_LOOKUP_RESULT_OUR_OWN;
|
||||
return m_isOurOwn;
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{AvahiServiceEntry} is equal to \a other; otherwise returns false.*/
|
||||
bool AvahiServiceEntry::operator ==(const AvahiServiceEntry &other) const
|
||||
/*! Returns true if this \l{ZeroConfServiceEntry} is equal to \a other; otherwise returns false.*/
|
||||
bool ZeroConfServiceEntry::operator ==(const ZeroConfServiceEntry &other) const
|
||||
{
|
||||
return other.name() == m_name &&
|
||||
other.serviceType() == m_serviceType &&
|
||||
@ -157,20 +154,24 @@ bool AvahiServiceEntry::operator ==(const AvahiServiceEntry &other) const
|
||||
other.hostName() == m_hostName &&
|
||||
other.port() == m_port &&
|
||||
other.protocol() == m_protocol &&
|
||||
other.flags() == m_flags &&
|
||||
other.isChached() == m_isCached &&
|
||||
other.isWideArea() == m_isWideArea &&
|
||||
other.isMulticast() == m_isMulticast &&
|
||||
other.isLocal() == m_isLocal &&
|
||||
other.isOurOwn() == m_isOurOwn &&
|
||||
other.txt() == m_txt;
|
||||
}
|
||||
|
||||
/*! Returns true if this \l{AvahiServiceEntry} is not equal to \a other; otherwise returns false.*/
|
||||
bool AvahiServiceEntry::operator !=(const AvahiServiceEntry &other) const
|
||||
/*! Returns true if this \l{ZeroConfServiceEntry} is not equal to \a other; otherwise returns false.*/
|
||||
bool ZeroConfServiceEntry::operator !=(const ZeroConfServiceEntry &other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
/*! Writes the given \a entry to the specified \a dbg.*/
|
||||
QDebug operator <<(QDebug dbg, const AvahiServiceEntry &entry)
|
||||
QDebug operator <<(QDebug dbg, const ZeroConfServiceEntry &entry)
|
||||
{
|
||||
dbg.nospace() << "AvahiServiceEntry(";
|
||||
dbg.nospace() << "ZeroConfServiceEntry(";
|
||||
dbg << entry.name() << ")" << endl;
|
||||
dbg << " location: " << entry.hostAddress().toString() << ":" << entry.port() << endl;
|
||||
dbg << " hostname: " << entry.hostName() << endl;
|
||||
@ -20,23 +20,21 @@
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef AVAHISERVICEENTRY_H
|
||||
#define AVAHISERVICEENTRY_H
|
||||
#ifndef ZEROCONFSERVICEENTRY_H
|
||||
#define ZEROCONFSERVICEENTRY_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QHostAddress>
|
||||
#include <QAbstractSocket>
|
||||
|
||||
#include <avahi-client/publish.h>
|
||||
|
||||
#include "libnymea.h"
|
||||
|
||||
class LIBNYMEA_EXPORT AvahiServiceEntry
|
||||
class LIBNYMEA_EXPORT ZeroConfServiceEntry
|
||||
{
|
||||
public:
|
||||
AvahiServiceEntry();
|
||||
AvahiServiceEntry(QString name, QString serviceType, QHostAddress hostAddress, QString domain, QString hostName, quint16 port, QAbstractSocket::NetworkLayerProtocol protocol, QStringList txt, AvahiLookupResultFlags flags);
|
||||
ZeroConfServiceEntry();
|
||||
ZeroConfServiceEntry(QString name, QString serviceType, QHostAddress hostAddress, QString domain, QString hostName, quint16 port, QAbstractSocket::NetworkLayerProtocol protocol, QStringList txt, bool cached, bool isWideArea, bool isMulticase, bool isLocal, bool isOurOwn);
|
||||
|
||||
QString name() const;
|
||||
QString serviceType() const;
|
||||
@ -45,7 +43,6 @@ public:
|
||||
QString hostName() const;
|
||||
quint16 port() const;
|
||||
QAbstractSocket::NetworkLayerProtocol protocol() const;
|
||||
AvahiLookupResultFlags flags() const;
|
||||
QStringList txt() const;
|
||||
|
||||
bool isValid() const;
|
||||
@ -56,8 +53,8 @@ public:
|
||||
bool isLocal() const;
|
||||
bool isOurOwn() const;
|
||||
|
||||
bool operator ==(const AvahiServiceEntry &other) const;
|
||||
bool operator !=(const AvahiServiceEntry &other) const;
|
||||
bool operator ==(const ZeroConfServiceEntry &other) const;
|
||||
bool operator !=(const ZeroConfServiceEntry &other) const;
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
@ -68,11 +65,15 @@ private:
|
||||
quint16 m_port;
|
||||
QAbstractSocket::NetworkLayerProtocol m_protocol;
|
||||
QStringList m_txt;
|
||||
AvahiLookupResultFlags m_flags;
|
||||
|
||||
bool m_isCached = false;
|
||||
bool m_isWideArea = false;
|
||||
bool m_isMulticast = false;
|
||||
bool m_isLocal = false;
|
||||
bool m_isOurOwn = false;
|
||||
};
|
||||
|
||||
QDebug operator <<(QDebug dbg, const AvahiServiceEntry &entry);
|
||||
Q_DECLARE_METATYPE(AvahiServiceEntry)
|
||||
QDebug operator <<(QDebug dbg, const ZeroConfServiceEntry &entry);
|
||||
Q_DECLARE_METATYPE(ZeroConfServiceEntry)
|
||||
|
||||
#endif // AVAHISERVICEENTRY_H
|
||||
#endif // ZEROCONFSERVICEENTRY_H
|
||||
59
libnymea/network/zeroconf/zeroconfservicepublisher.cpp
Normal file
59
libnymea/network/zeroconf/zeroconfservicepublisher.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2.1 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; If not, see *
|
||||
* <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "zeroconfservicepublisher.h"
|
||||
|
||||
ZeroConfServicePublisher::ZeroConfServicePublisher(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ZeroConfServicePublisher::registerService
|
||||
* \param id An ID used to track this service instance. Pick a unique id and use the same for updating or unregistering the service
|
||||
* \param name The name as it should appear on the network. Note that it might be changed when collisions appear
|
||||
* \param hostAddress The hostAddress the server is running
|
||||
* \param port The port of the server
|
||||
* \param serviceType The service type as it should appear on the network, for instance "_http.tcp"
|
||||
* \param txtRecords A Map of txt records that should be published with this service
|
||||
* \return
|
||||
*/
|
||||
|
||||
bool ZeroConfServicePublisher::registerService(const QString &id, const QString &name, const QHostAddress &hostAddress, const quint16 &port, const QString &serviceType, const QHash<QString, QString> &txtRecords)
|
||||
{
|
||||
Q_UNUSED(id)
|
||||
Q_UNUSED(name)
|
||||
Q_UNUSED(hostAddress)
|
||||
Q_UNUSED(port)
|
||||
Q_UNUSED(serviceType)
|
||||
Q_UNUSED(txtRecords)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ZeroConfServicePublisher::unregisterService
|
||||
* \param id The id previously used to register the server
|
||||
*/
|
||||
void ZeroConfServicePublisher::unregisterService(const QString &id)
|
||||
{
|
||||
Q_UNUSED(id)
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
@ -20,59 +20,21 @@
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef QTAVAHICLIENT_H
|
||||
#define QTAVAHICLIENT_H
|
||||
#ifndef ZEROCONFSERVICEPUBLISHER_H
|
||||
#define ZEROCONFSERVICEPUBLISHER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <avahi-client/client.h>
|
||||
#include <QHostAddress>
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
class QtAvahiClient : public QObject
|
||||
class ZeroConfServicePublisher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS(QtAvahiClientState)
|
||||
|
||||
public:
|
||||
enum QtAvahiClientState {
|
||||
QtAvahiClientStateNone,
|
||||
QtAvahiClientStateRunning,
|
||||
QtAvahiClientStateFailure,
|
||||
QtAvahiClientStateCollision,
|
||||
QtAvahiClientStateRegistering,
|
||||
QtAvahiClientStateConnecting
|
||||
};
|
||||
|
||||
explicit QtAvahiClient(QObject *parent = nullptr);
|
||||
~QtAvahiClient();
|
||||
|
||||
QtAvahiClientState state() const;
|
||||
|
||||
private:
|
||||
friend class QtAvahiService;
|
||||
friend class QtAvahiServiceBrowserImplementation;
|
||||
friend class QtAvahiServiceBrowserImplementationPrivate;
|
||||
|
||||
const AvahiPoll *m_poll;
|
||||
AvahiClient *m_client;
|
||||
int error;
|
||||
QtAvahiClientState m_state;
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
QString errorString() const;
|
||||
|
||||
static void callback(AvahiClient *client, AvahiClientState state, void *userdata);
|
||||
|
||||
private slots:
|
||||
void onClientStateChanged(const QtAvahiClientState &state);
|
||||
|
||||
signals:
|
||||
void clientStateChanged(const QtAvahiClientState &state);
|
||||
void clientStateChangedInternal(const QtAvahiClientState &state);
|
||||
explicit ZeroConfServicePublisher(QObject *parent = nullptr);
|
||||
virtual ~ZeroConfServicePublisher() = default;
|
||||
|
||||
virtual bool registerService(const QString &id, const QString &name, const QHostAddress &hostAddress, const quint16 &port, const QString &serviceType, const QHash<QString, QString> &txtRecords);
|
||||
virtual void unregisterService(const QString &id);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QTAVAHICLIENT_H
|
||||
#endif // ZEROCONFSERVICEPUBLISHER_H
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
@ -20,57 +20,24 @@
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef QTAVAHISERVICEBROWSERIMPLEMENTATION_H
|
||||
#define QTAVAHISERVICEBROWSERIMPLEMENTATION_H
|
||||
#include "platformzeroconfcontroller.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <avahi-client/lookup.h>
|
||||
#include "network/zeroconf/zeroconfservicebrowser.h"
|
||||
#include "network/zeroconf/zeroconfservicepublisher.h"
|
||||
|
||||
#include "qtavahiclient.h"
|
||||
|
||||
#include "network/avahi/avahiserviceentry.h"
|
||||
#include "network/avahi/qtavahiservicebrowser.h"
|
||||
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
class QtAvahiServiceBrowserImplementationPrivate;
|
||||
|
||||
class QtAvahiServiceBrowserImplementation : public QtAvahiServiceBrowser
|
||||
PlatformZeroConfController::PlatformZeroConfController(QObject *parent):
|
||||
QObject(parent)
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class HardwareManagerImplementation;
|
||||
|
||||
public:
|
||||
explicit QtAvahiServiceBrowserImplementation(QObject *parent = nullptr);
|
||||
~QtAvahiServiceBrowserImplementation() override;
|
||||
|
||||
QList<AvahiServiceEntry> serviceEntries() const override;
|
||||
|
||||
bool available() const override;
|
||||
bool enabled() const override;
|
||||
|
||||
private slots:
|
||||
void onClientStateChanged(const QtAvahiClient::QtAvahiClientState &state);
|
||||
|
||||
protected:
|
||||
void setEnabled(bool enabled) override;
|
||||
|
||||
private:
|
||||
bool m_available = false;
|
||||
bool m_enabled = false;
|
||||
|
||||
QtAvahiServiceBrowserImplementationPrivate *d_ptr;
|
||||
|
||||
QList<AvahiServiceEntry> m_serviceEntries;
|
||||
QStringList m_serviceTypes;
|
||||
|
||||
void createServiceBrowser(const char* serviceType);
|
||||
|
||||
Q_DECLARE_PRIVATE(QtAvahiServiceBrowserImplementation)
|
||||
};
|
||||
|
||||
m_zeroConfBrowserStub = new ZeroConfServiceBrowser(this);
|
||||
m_zeroConfPublisherStub = new ZeroConfServicePublisher(this);
|
||||
}
|
||||
|
||||
#endif // QTAVAHISERVICEBROWSERIMPLEMENTATION_H
|
||||
ZeroConfServiceBrowser *PlatformZeroConfController::zeroConfServiceBrowser() const
|
||||
{
|
||||
return m_zeroConfBrowserStub;
|
||||
}
|
||||
|
||||
ZeroConfServicePublisher *PlatformZeroConfController::zeroConfServicePublisher() const
|
||||
{
|
||||
return m_zeroConfPublisherStub;
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* *
|
||||
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
|
||||
* *
|
||||
* This file is part of nymea. *
|
||||
* *
|
||||
@ -20,43 +20,29 @@
|
||||
* *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef QTAVAHISERVICEPRIVATE_P
|
||||
#define QTAVAHISERVICEPRIVATE_P
|
||||
#ifndef PLATFORMZEROCONFCONTROLLER_H
|
||||
#define PLATFORMZEROCONFCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
#include "qtavahiservice.h"
|
||||
#include "qtavahiclient.h"
|
||||
class ZeroConfServiceBrowser;
|
||||
class ZeroConfServicePublisher;
|
||||
|
||||
#include <avahi-client/publish.h>
|
||||
#include <avahi-common/error.h>
|
||||
#include <avahi-common/alternative.h>
|
||||
|
||||
namespace nymeaserver {
|
||||
|
||||
class QtAvahiServicePrivate
|
||||
class PlatformZeroConfController: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QtAvahiServicePrivate();
|
||||
explicit PlatformZeroConfController(QObject *parent = nullptr);
|
||||
virtual ~PlatformZeroConfController() = default;
|
||||
|
||||
static void callback(AvahiEntryGroup *group, AvahiEntryGroupState state, void *userdata);
|
||||
|
||||
QtAvahiClient *client;
|
||||
AvahiEntryGroup *group;
|
||||
AvahiStringList *serviceList = nullptr;
|
||||
QString name;
|
||||
QHostAddress hostAddress;
|
||||
quint16 port;
|
||||
QString type;
|
||||
QHash<QString, QString> txtRecords;
|
||||
int error;
|
||||
|
||||
static AvahiStringList *createTxtList(const QHash<QString, QString> &txt);
|
||||
virtual ZeroConfServiceBrowser *zeroConfServiceBrowser() const;
|
||||
virtual ZeroConfServicePublisher *zeroConfServicePublisher() const;
|
||||
|
||||
private:
|
||||
ZeroConfServiceBrowser *m_zeroConfBrowserStub = nullptr;
|
||||
ZeroConfServicePublisher *m_zeroConfPublisherStub = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QTAVAHISERVICEPRIVATE_P
|
||||
Q_DECLARE_INTERFACE(PlatformZeroConfController, "io.nymea.PlatformZeroConfController")
|
||||
|
||||
#endif // PLATFORMZEROCONFCONTROLLER_H
|
||||
@ -8,7 +8,7 @@ INCLUDEPATH += $$top_srcdir/libnymea \
|
||||
LIBS += -L$$top_builddir/libnymea/ -lnymea \
|
||||
-L$$top_builddir/libnymea-core/ -lnymea-core \
|
||||
-L$$top_builddir/plugins/mock/ \
|
||||
-lssl -lcrypto -lavahi-common -lavahi-client -lnymea-remoteproxyclient
|
||||
-lssl -lcrypto -lnymea-remoteproxyclient
|
||||
|
||||
SOURCES += ../nymeatestbase.cpp \
|
||||
|
||||
|
||||
Reference in New Issue
Block a user