2018-12-30 22:07:53 +01:00
|
|
|
#include <ssdp/SSDPHandler.h>
|
|
|
|
|
|
|
|
#include <webserver/WebServer.h>
|
|
|
|
#include "SSDPDescription.h"
|
|
|
|
#include <hyperion/Hyperion.h>
|
|
|
|
#include <HyperionConfig.h>
|
2019-07-14 22:43:22 +02:00
|
|
|
#include <hyperion/AuthManager.h>
|
2018-12-30 22:07:53 +01:00
|
|
|
|
|
|
|
#include <QNetworkInterface>
|
2021-11-16 18:12:56 +01:00
|
|
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
2018-12-30 22:07:53 +01:00
|
|
|
#include <QNetworkConfigurationManager>
|
2021-11-16 18:12:56 +01:00
|
|
|
#endif
|
2018-12-30 22:07:53 +01:00
|
|
|
|
2020-07-27 20:00:36 +02:00
|
|
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
|
|
|
#include <QRandomGenerator>
|
|
|
|
#endif
|
|
|
|
|
2021-09-15 10:31:56 +02:00
|
|
|
static const QString SSDP_IDENTIFIER("urn:hyperion-project.org:device:basic:1");
|
2020-03-11 22:18:08 +01:00
|
|
|
|
2020-10-18 17:05:07 +02:00
|
|
|
SSDPHandler::SSDPHandler(WebServer* webserver, quint16 flatBufPort, quint16 protoBufPort, quint16 jsonServerPort, quint16 sslPort, const QString& name, QObject * parent)
|
2018-12-30 22:07:53 +01:00
|
|
|
: SSDPServer(parent)
|
|
|
|
, _webserver(webserver)
|
|
|
|
, _localAddress()
|
2021-11-16 18:12:56 +01:00
|
|
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
2018-12-30 22:07:53 +01:00
|
|
|
, _NCA(nullptr)
|
2021-11-16 18:12:56 +01:00
|
|
|
#endif
|
2018-12-30 22:07:53 +01:00
|
|
|
{
|
2019-08-17 09:44:57 +02:00
|
|
|
setFlatBufPort(flatBufPort);
|
2020-10-18 17:05:07 +02:00
|
|
|
setProtoBufPort(protoBufPort);
|
2019-08-17 09:44:57 +02:00
|
|
|
setJsonServerPort(jsonServerPort);
|
2020-10-18 17:05:07 +02:00
|
|
|
setSSLServerPort(sslPort);
|
2020-02-26 18:54:56 +01:00
|
|
|
setHyperionName(name);
|
2018-12-30 22:07:53 +01:00
|
|
|
}
|
|
|
|
|
2019-08-14 21:19:05 +02:00
|
|
|
SSDPHandler::~SSDPHandler()
|
|
|
|
{
|
add Hue EntertainmentAPI + Forwarder & other Fixes (#592)
* whitespaces + typo fixes
* JS / LGTM fixes
* SSDP Handler crash fix
* MessageForwarder handlePriorityChanges Slave fixes
* use aboutToQuit Signal
* complete rewriten Hue Entertainment API structure
combined Philips Hue and Entertainment API
with new MbedTLS based SSL UDP Provider
* add required cross-compile submodules
* logical rebuild fn: initLeds, setLights + new logs
-more detailed checks and error handling inside iniLeds and setLights
- logical script procedure before ProviderUdpSSL init
- first steps for multiple ProviderUdpSSL usage
- better fallback support to old RestAPI, if entertainment api is not supported
- just 4 u LordGrey: new log fn for cosmetic config outputs ;)
* add OSX CompileHowTo - undo from CrossCompileHowTo
* whitespace fixes
* lightID toString fix
* fix unsigned int E-API + debug output
* bugfixes, reworked black signal detection, wizard:
- change device config field light-ids from int to string -> real unsigned int fix
- add signal detection brightness minimum threshold value
0.0 for 0% brightness - 1.0 for 100% brightness to count for blacklight signal detection
reason: input may not 100% black, like mine - i have a deep dark gray input signal
-> my threshold value is set to 0.005 for 0.5% minimum brightness = 1 (from max 255) to count as black
- wizard optimations, with fallback without entertainment support (beta state)
- whitespace fixes
* cleanup + minor fixes
* change fixed Hue UPD SSL config to _devConfig paras
* Hotfix SSL Connection, new light models, wizard:
- Fix UPD SSL Connection failed Problems
- add new supported gamut C light models: LCG002, LCA001, LCA002, LCA003
- wizard: extend fallback support to classic mode + hints
* whitespace, typo fix
* uncheck useEntertainmentAPI, if noAPISupport detected + hint
* coredump fix -> add _blackLightsTimer nullptr init
* code cleanup / remove old debugs + whitespacefixes
* add gamut C LCP001, LCP002
* SSL UDP config made more flexible + remove qDebug
-> switch to hyerion.ng _log
-> replace logCommand with verbose
-> code cleanups etc...
* extended mbedtls debugging infos
* add adjustable ssl timeout settings
* error handling
* streamdebugger bugfixes
* UPDSSL psk / psk_identity bugfixes! + hue wizard fn typo fix +
- verbose option available without dependencies
- whitespace fixes
* Philips Hue Assistant now recognizes non-original bridges better...
+ Added note if no clientkey is set when using the entertainment API
+ User creation (+ clientkey) for non-original bridges can now also be used
+ Minor changes and bug fixes
* CMAKE mbedTLS detection
* minor bug fixes + code cleanups
* FindMbedTLS.cmake remove Path-Hints + wizard.js: ajax timeout handling
Test - content_grabber.js: run relevant code only, if V4L2_AVAIL is true:
conf_grabber don't displays other devices, if V4L2 is not available
* compile mbedtls via cmake as static lib
* remove libmbedtls-dev from compileHowto / scripts
* Fix Windows build
* Fix windows build (part 2)
* removed unnecessary osx x11 include directory path
* QTimer Shutdown bugfix
* cmake win32 fix + minor bugfixes
* cmake debug msg used mbedtls libs
* Bugfix: noSignalDetection wasn't switchedOn again
if no signal was previously detected
* Some code fixes based on alerts from lgtm.com
Co-authored-by: Paulchen Panther <16664240+Paulchen-Panther@users.noreply.github.com>
2020-05-22 19:40:50 +02:00
|
|
|
stopServer();
|
2019-08-14 21:19:05 +02:00
|
|
|
}
|
|
|
|
|
2018-12-30 22:07:53 +01:00
|
|
|
void SSDPHandler::initServer()
|
|
|
|
{
|
2019-08-14 21:19:05 +02:00
|
|
|
_uuid = AuthManager::getInstance()->getID();
|
|
|
|
SSDPServer::setUuid(_uuid);
|
|
|
|
|
|
|
|
// announce targets
|
|
|
|
_deviceList.push_back("upnp:rootdevice");
|
|
|
|
_deviceList.push_back("uuid:"+_uuid);
|
2021-09-15 10:31:56 +02:00
|
|
|
_deviceList.push_back(SSDP_IDENTIFIER);
|
2019-08-14 21:19:05 +02:00
|
|
|
|
2018-12-30 22:07:53 +01:00
|
|
|
// prep server
|
|
|
|
SSDPServer::initServer();
|
2021-11-16 18:12:56 +01:00
|
|
|
|
|
|
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
2018-12-30 22:07:53 +01:00
|
|
|
_NCA = new QNetworkConfigurationManager(this);
|
2021-11-16 18:12:56 +01:00
|
|
|
connect(_NCA, &QNetworkConfigurationManager::configurationChanged, this, &SSDPHandler::handleNetworkConfigurationChanged);
|
|
|
|
#endif
|
|
|
|
|
2018-12-30 22:07:53 +01:00
|
|
|
// listen for mSearchRequestes
|
|
|
|
connect(this, &SSDPServer::msearchRequestReceived, this, &SSDPHandler::handleMSearchRequest);
|
|
|
|
|
|
|
|
// get localAddress from interface
|
|
|
|
if(!getLocalAddress().isEmpty())
|
|
|
|
{
|
|
|
|
_localAddress = getLocalAddress();
|
|
|
|
}
|
|
|
|
|
|
|
|
// startup if localAddress is found
|
2020-07-22 16:43:24 +02:00
|
|
|
bool isInited = false;
|
|
|
|
QMetaObject::invokeMethod(_webserver, "isInited", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, isInited));
|
|
|
|
|
|
|
|
if(!_localAddress.isEmpty() && isInited)
|
2018-12-30 22:07:53 +01:00
|
|
|
{
|
|
|
|
handleWebServerStateChange(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
add Hue EntertainmentAPI + Forwarder & other Fixes (#592)
* whitespaces + typo fixes
* JS / LGTM fixes
* SSDP Handler crash fix
* MessageForwarder handlePriorityChanges Slave fixes
* use aboutToQuit Signal
* complete rewriten Hue Entertainment API structure
combined Philips Hue and Entertainment API
with new MbedTLS based SSL UDP Provider
* add required cross-compile submodules
* logical rebuild fn: initLeds, setLights + new logs
-more detailed checks and error handling inside iniLeds and setLights
- logical script procedure before ProviderUdpSSL init
- first steps for multiple ProviderUdpSSL usage
- better fallback support to old RestAPI, if entertainment api is not supported
- just 4 u LordGrey: new log fn for cosmetic config outputs ;)
* add OSX CompileHowTo - undo from CrossCompileHowTo
* whitespace fixes
* lightID toString fix
* fix unsigned int E-API + debug output
* bugfixes, reworked black signal detection, wizard:
- change device config field light-ids from int to string -> real unsigned int fix
- add signal detection brightness minimum threshold value
0.0 for 0% brightness - 1.0 for 100% brightness to count for blacklight signal detection
reason: input may not 100% black, like mine - i have a deep dark gray input signal
-> my threshold value is set to 0.005 for 0.5% minimum brightness = 1 (from max 255) to count as black
- wizard optimations, with fallback without entertainment support (beta state)
- whitespace fixes
* cleanup + minor fixes
* change fixed Hue UPD SSL config to _devConfig paras
* Hotfix SSL Connection, new light models, wizard:
- Fix UPD SSL Connection failed Problems
- add new supported gamut C light models: LCG002, LCA001, LCA002, LCA003
- wizard: extend fallback support to classic mode + hints
* whitespace, typo fix
* uncheck useEntertainmentAPI, if noAPISupport detected + hint
* coredump fix -> add _blackLightsTimer nullptr init
* code cleanup / remove old debugs + whitespacefixes
* add gamut C LCP001, LCP002
* SSL UDP config made more flexible + remove qDebug
-> switch to hyerion.ng _log
-> replace logCommand with verbose
-> code cleanups etc...
* extended mbedtls debugging infos
* add adjustable ssl timeout settings
* error handling
* streamdebugger bugfixes
* UPDSSL psk / psk_identity bugfixes! + hue wizard fn typo fix +
- verbose option available without dependencies
- whitespace fixes
* Philips Hue Assistant now recognizes non-original bridges better...
+ Added note if no clientkey is set when using the entertainment API
+ User creation (+ clientkey) for non-original bridges can now also be used
+ Minor changes and bug fixes
* CMAKE mbedTLS detection
* minor bug fixes + code cleanups
* FindMbedTLS.cmake remove Path-Hints + wizard.js: ajax timeout handling
Test - content_grabber.js: run relevant code only, if V4L2_AVAIL is true:
conf_grabber don't displays other devices, if V4L2 is not available
* compile mbedtls via cmake as static lib
* remove libmbedtls-dev from compileHowto / scripts
* Fix Windows build
* Fix windows build (part 2)
* removed unnecessary osx x11 include directory path
* QTimer Shutdown bugfix
* cmake win32 fix + minor bugfixes
* cmake debug msg used mbedtls libs
* Bugfix: noSignalDetection wasn't switchedOn again
if no signal was previously detected
* Some code fixes based on alerts from lgtm.com
Co-authored-by: Paulchen Panther <16664240+Paulchen-Panther@users.noreply.github.com>
2020-05-22 19:40:50 +02:00
|
|
|
void SSDPHandler::stopServer()
|
|
|
|
{
|
|
|
|
sendAnnounceList(false);
|
|
|
|
SSDPServer::stop();
|
|
|
|
}
|
|
|
|
|
2020-08-08 13:09:15 +02:00
|
|
|
void SSDPHandler::handleSettingsUpdate(settings::type type, const QJsonDocument& config)
|
2018-12-30 22:07:53 +01:00
|
|
|
{
|
2020-07-12 09:19:59 +02:00
|
|
|
const QJsonObject& obj = config.object();
|
|
|
|
|
2018-12-30 22:07:53 +01:00
|
|
|
if(type == settings::FLATBUFSERVER)
|
|
|
|
{
|
2019-08-17 09:44:57 +02:00
|
|
|
if(obj["port"].toInt() != SSDPServer::getFlatBufPort())
|
2018-12-30 22:07:53 +01:00
|
|
|
{
|
2019-08-17 09:44:57 +02:00
|
|
|
SSDPServer::setFlatBufPort(obj["port"].toInt());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-18 17:05:07 +02:00
|
|
|
if(type == settings::PROTOSERVER)
|
|
|
|
{
|
|
|
|
if(obj["port"].toInt() != SSDPServer::getProtoBufPort())
|
|
|
|
{
|
|
|
|
SSDPServer::setProtoBufPort(obj["port"].toInt());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-17 09:44:57 +02:00
|
|
|
if(type == settings::JSONSERVER)
|
|
|
|
{
|
|
|
|
if(obj["port"].toInt() != SSDPServer::getJsonServerPort())
|
|
|
|
{
|
|
|
|
SSDPServer::setJsonServerPort(obj["port"].toInt());
|
2018-12-30 22:07:53 +01:00
|
|
|
}
|
|
|
|
}
|
2020-02-26 18:54:56 +01:00
|
|
|
|
2020-10-18 17:05:07 +02:00
|
|
|
if(type == settings::WEBSERVER)
|
|
|
|
{
|
|
|
|
if(obj["sslPort"].toInt() != SSDPServer::getSSLServerPort())
|
|
|
|
{
|
|
|
|
SSDPServer::setSSLServerPort(obj["sslPort"].toInt());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-26 18:54:56 +01:00
|
|
|
if (type == settings::GENERAL)
|
|
|
|
{
|
|
|
|
if (obj["name"].toString() != SSDPServer::getHyperionName())
|
|
|
|
{
|
|
|
|
SSDPServer::setHyperionName(obj["name"].toString());
|
|
|
|
}
|
|
|
|
}
|
2018-12-30 22:07:53 +01:00
|
|
|
}
|
|
|
|
|
2020-08-08 13:09:15 +02:00
|
|
|
void SSDPHandler::handleWebServerStateChange(bool newState)
|
2018-12-30 22:07:53 +01:00
|
|
|
{
|
|
|
|
if(newState)
|
|
|
|
{
|
|
|
|
// refresh info
|
2020-07-22 16:43:24 +02:00
|
|
|
QMetaObject::invokeMethod(_webserver, "setSSDPDescription", Qt::BlockingQueuedConnection, Q_ARG(QString, buildDesc()));
|
2018-12-30 22:07:53 +01:00
|
|
|
setDescriptionAddress(getDescAddress());
|
|
|
|
if(start())
|
2019-08-14 21:19:05 +02:00
|
|
|
sendAnnounceList(true);
|
2018-12-30 22:07:53 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-07-22 16:43:24 +02:00
|
|
|
QMetaObject::invokeMethod(_webserver, "setSSDPDescription", Qt::BlockingQueuedConnection, Q_ARG(QString, ""));
|
2019-08-14 21:19:05 +02:00
|
|
|
sendAnnounceList(false);
|
2018-12-30 22:07:53 +01:00
|
|
|
stop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-16 18:12:56 +01:00
|
|
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
2018-12-30 22:07:53 +01:00
|
|
|
void SSDPHandler::handleNetworkConfigurationChanged(const QNetworkConfiguration &config)
|
|
|
|
{
|
|
|
|
// get localAddress from interface
|
2020-07-12 18:27:24 +02:00
|
|
|
QString localAddress = getLocalAddress();
|
|
|
|
if(!localAddress.isEmpty() && _localAddress != localAddress)
|
2018-12-30 22:07:53 +01:00
|
|
|
{
|
2020-07-12 18:27:24 +02:00
|
|
|
// revoke old ip
|
|
|
|
sendAnnounceList(false);
|
2018-12-30 22:07:53 +01:00
|
|
|
|
2020-07-12 18:27:24 +02:00
|
|
|
// update desc & notify new ip
|
|
|
|
_localAddress = localAddress;
|
2020-07-22 16:43:24 +02:00
|
|
|
QMetaObject::invokeMethod(_webserver, "setSSDPDescription", Qt::BlockingQueuedConnection, Q_ARG(QString, buildDesc()));
|
2020-07-12 18:27:24 +02:00
|
|
|
setDescriptionAddress(getDescAddress());
|
|
|
|
sendAnnounceList(true);
|
2018-12-30 22:07:53 +01:00
|
|
|
}
|
|
|
|
}
|
2021-11-16 18:12:56 +01:00
|
|
|
#endif
|
2018-12-30 22:07:53 +01:00
|
|
|
|
2020-07-12 09:19:59 +02:00
|
|
|
QString SSDPHandler::getLocalAddress() const
|
2018-12-30 22:07:53 +01:00
|
|
|
{
|
|
|
|
// get the first valid IPv4 address. This is probably not that one we actually want to announce
|
2020-07-12 09:19:59 +02:00
|
|
|
for(const auto & address : QNetworkInterface::allAddresses())
|
2018-12-30 22:07:53 +01:00
|
|
|
{
|
|
|
|
// is valid when, no loopback, IPv4
|
2020-07-12 09:19:59 +02:00
|
|
|
if (!address.isLoopback() && address.protocol() == QAbstractSocket::IPv4Protocol)
|
2018-12-30 22:07:53 +01:00
|
|
|
{
|
|
|
|
return address.toString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2020-08-08 13:09:15 +02:00
|
|
|
void SSDPHandler::handleMSearchRequest(const QString& target, const QString& mx, const QString address, quint16 port)
|
2018-12-30 22:07:53 +01:00
|
|
|
{
|
2020-06-28 23:19:06 +02:00
|
|
|
const auto respond = [=] () {
|
|
|
|
// when searched for all devices / root devices / basic device
|
|
|
|
if(target == "ssdp:all")
|
2021-09-15 10:31:56 +02:00
|
|
|
sendMSearchResponse(SSDP_IDENTIFIER, address, port);
|
|
|
|
else if(target == "upnp:rootdevice" || target == "urn:schemas-upnp-org:device:basic:1" || target == SSDP_IDENTIFIER)
|
2020-06-28 23:19:06 +02:00
|
|
|
sendMSearchResponse(target, address, port);
|
|
|
|
};
|
|
|
|
|
|
|
|
bool ok = false;
|
|
|
|
int maxDelay = mx.toInt(&ok);
|
|
|
|
if (ok)
|
|
|
|
{
|
|
|
|
/* Pick a random delay between 0 and MX seconds */
|
2020-07-27 20:00:36 +02:00
|
|
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
|
|
|
int randomDelay = QRandomGenerator::global()->generate() % (maxDelay * 1000);
|
|
|
|
#else
|
2020-06-28 23:19:06 +02:00
|
|
|
int randomDelay = qrand() % (maxDelay * 1000);
|
2020-07-27 20:00:36 +02:00
|
|
|
#endif
|
2020-06-28 23:19:06 +02:00
|
|
|
QTimer::singleShot(randomDelay, respond);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* MX Header is not valid.
|
|
|
|
* Send response without delay */
|
|
|
|
respond();
|
|
|
|
}
|
2018-12-30 22:07:53 +01:00
|
|
|
}
|
|
|
|
|
2020-07-12 09:19:59 +02:00
|
|
|
QString SSDPHandler::getDescAddress() const
|
2018-12-30 22:07:53 +01:00
|
|
|
{
|
|
|
|
return getBaseAddress()+"description.xml";
|
|
|
|
}
|
|
|
|
|
2020-07-12 09:19:59 +02:00
|
|
|
QString SSDPHandler::getBaseAddress() const
|
2018-12-30 22:07:53 +01:00
|
|
|
{
|
2020-07-22 16:43:24 +02:00
|
|
|
quint16 port = 0;
|
|
|
|
QMetaObject::invokeMethod(_webserver, "getPort", Qt::BlockingQueuedConnection, Q_RETURN_ARG(quint16, port));
|
|
|
|
return QString("http://%1:%2/").arg(_localAddress).arg(port);
|
2018-12-30 22:07:53 +01:00
|
|
|
}
|
|
|
|
|
2020-07-12 09:19:59 +02:00
|
|
|
QString SSDPHandler::buildDesc() const
|
2018-12-30 22:07:53 +01:00
|
|
|
{
|
2021-09-15 10:31:56 +02:00
|
|
|
/// %1 base url http://192.168.0.177:8090/
|
|
|
|
/// %2 friendly name Hyperion (192.168.0.177)
|
2018-12-30 22:07:53 +01:00
|
|
|
/// %3 modelNumber 2.0.0
|
|
|
|
/// %4 serialNumber / UDN (H ID) Fjsa723dD0....
|
2020-10-18 17:05:07 +02:00
|
|
|
/// %5 json port 19444
|
|
|
|
/// %6 ssl server port 8092
|
|
|
|
/// %7 protobuf port 19445
|
|
|
|
/// %8 flatbuf port 19400
|
|
|
|
|
|
|
|
return SSDP_DESCRIPTION.arg(
|
|
|
|
getBaseAddress(),
|
|
|
|
QString("Hyperion (%1)").arg(_localAddress),
|
|
|
|
QString(HYPERION_VERSION),
|
|
|
|
_uuid,
|
|
|
|
QString::number(SSDPServer::getJsonServerPort()),
|
|
|
|
QString::number(SSDPServer::getSSLServerPort()),
|
|
|
|
QString::number(SSDPServer::getProtoBufPort()),
|
|
|
|
QString::number(SSDPServer::getFlatBufPort())
|
|
|
|
);
|
2019-08-14 21:19:05 +02:00
|
|
|
}
|
|
|
|
|
2020-08-08 13:09:15 +02:00
|
|
|
void SSDPHandler::sendAnnounceList(bool alive)
|
2020-07-12 09:19:59 +02:00
|
|
|
{
|
2019-08-14 21:19:05 +02:00
|
|
|
for(const auto & entry : _deviceList){
|
|
|
|
alive ? SSDPServer::sendAlive(entry) : SSDPServer::sendByeBye(entry);
|
|
|
|
}
|
2018-12-30 22:07:53 +01:00
|
|
|
}
|
2020-07-22 16:43:24 +02:00
|
|
|
|