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>
|
|
|
|
#include <QNetworkConfigurationManager>
|
|
|
|
|
|
|
|
SSDPHandler::SSDPHandler(WebServer* webserver, const quint16& flatBufPort, QObject * parent)
|
|
|
|
: SSDPServer(parent)
|
|
|
|
, _webserver(webserver)
|
|
|
|
, _localAddress()
|
|
|
|
, _NCA(nullptr)
|
|
|
|
{
|
|
|
|
_flatbufPort = flatBufPort;
|
|
|
|
setFlatBufPort(_flatbufPort);
|
|
|
|
}
|
|
|
|
|
2019-08-14 21:19:05 +02:00
|
|
|
SSDPHandler::~SSDPHandler()
|
|
|
|
{
|
|
|
|
sendAnnounceList(false);
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
_deviceList.push_back("urn:hyperion-project.org:device:basic:1");
|
|
|
|
|
2018-12-30 22:07:53 +01:00
|
|
|
// prep server
|
|
|
|
SSDPServer::initServer();
|
|
|
|
|
|
|
|
_NCA = new QNetworkConfigurationManager(this);
|
|
|
|
|
|
|
|
// listen for mSearchRequestes
|
|
|
|
connect(this, &SSDPServer::msearchRequestReceived, this, &SSDPHandler::handleMSearchRequest);
|
|
|
|
|
|
|
|
connect(_NCA, &QNetworkConfigurationManager::configurationChanged, this, &SSDPHandler::handleNetworkConfigurationChanged);
|
|
|
|
|
|
|
|
// get localAddress from interface
|
|
|
|
if(!getLocalAddress().isEmpty())
|
|
|
|
{
|
|
|
|
_localAddress = getLocalAddress();
|
|
|
|
}
|
|
|
|
|
|
|
|
// startup if localAddress is found
|
|
|
|
if(!_localAddress.isEmpty() && _webserver->isInited())
|
|
|
|
{
|
|
|
|
handleWebServerStateChange(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SSDPHandler::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)
|
|
|
|
{
|
|
|
|
if(type == settings::FLATBUFSERVER)
|
|
|
|
{
|
|
|
|
const QJsonObject& obj = config.object();
|
|
|
|
if(obj["port"].toInt() != _flatbufPort)
|
|
|
|
{
|
|
|
|
_flatbufPort = obj["port"].toInt();
|
|
|
|
setFlatBufPort(_flatbufPort);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SSDPHandler::handleWebServerStateChange(const bool newState)
|
|
|
|
{
|
|
|
|
if(newState)
|
|
|
|
{
|
|
|
|
// refresh info
|
|
|
|
_webserver->setSSDPDescription(buildDesc());
|
|
|
|
setDescriptionAddress(getDescAddress());
|
|
|
|
if(start())
|
2019-08-14 21:19:05 +02:00
|
|
|
sendAnnounceList(true);
|
2018-12-30 22:07:53 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_webserver->setSSDPDescription("");
|
2019-08-14 21:19:05 +02:00
|
|
|
sendAnnounceList(false);
|
2018-12-30 22:07:53 +01:00
|
|
|
stop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SSDPHandler::handleNetworkConfigurationChanged(const QNetworkConfiguration &config)
|
|
|
|
{
|
|
|
|
// get localAddress from interface
|
|
|
|
if(!getLocalAddress().isEmpty())
|
|
|
|
{
|
|
|
|
QString localAddress = getLocalAddress();
|
|
|
|
if(_localAddress != localAddress)
|
|
|
|
{
|
|
|
|
// revoke old ip
|
2019-08-14 21:19:05 +02:00
|
|
|
sendAnnounceList(false);
|
2018-12-30 22:07:53 +01:00
|
|
|
|
|
|
|
// update desc & notify new ip
|
|
|
|
_localAddress = localAddress;
|
|
|
|
_webserver->setSSDPDescription(buildDesc());
|
|
|
|
setDescriptionAddress(getDescAddress());
|
2019-08-14 21:19:05 +02:00
|
|
|
sendAnnounceList(true);
|
2018-12-30 22:07:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const QString SSDPHandler::getLocalAddress()
|
|
|
|
{
|
|
|
|
// get the first valid IPv4 address. This is probably not that one we actually want to announce
|
|
|
|
for( const auto & address : QNetworkInterface::allAddresses())
|
|
|
|
{
|
|
|
|
// is valid when, no loopback, IPv4
|
|
|
|
if (!address.isLoopback() && address.protocol() == QAbstractSocket::IPv4Protocol )
|
|
|
|
{
|
|
|
|
return address.toString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SSDPHandler::handleMSearchRequest(const QString& target, const QString& mx, const QString address, const quint16 & port)
|
|
|
|
{
|
|
|
|
// TODO Response delay according to MX field (sec) random between 0 and MX
|
|
|
|
|
|
|
|
// when searched for all devices / root devices / basic device
|
|
|
|
if(target == "ssdp:all" || target == "upnp:rootdevice" || target == "urn:schemas-upnp-org:device:basic:1" || target == "urn:hyperion-project.org:device:basic:1")
|
|
|
|
sendMSearchResponse(target, address, port);
|
|
|
|
}
|
|
|
|
|
|
|
|
const QString SSDPHandler::getDescAddress()
|
|
|
|
{
|
|
|
|
return getBaseAddress()+"description.xml";
|
|
|
|
}
|
|
|
|
|
|
|
|
const QString SSDPHandler::getBaseAddress()
|
|
|
|
{
|
|
|
|
return "http://"+_localAddress+":"+QString::number(_webserver->getPort())+"/";
|
|
|
|
}
|
|
|
|
|
|
|
|
const QString SSDPHandler::buildDesc()
|
|
|
|
{
|
|
|
|
/// %1 base url http://192.168.0.177:80/
|
|
|
|
/// %2 friendly name Hyperion 2.0.0 (192.168.0.177)
|
|
|
|
/// %3 modelNumber 2.0.0
|
|
|
|
/// %4 serialNumber / UDN (H ID) Fjsa723dD0....
|
2019-08-14 21:19:05 +02:00
|
|
|
return SSDP_DESCRIPTION.arg(getBaseAddress(), QString("Hyperion (%2)").arg(_localAddress), QString(HYPERION_VERSION), _uuid);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SSDPHandler::sendAnnounceList(const bool alive){
|
|
|
|
for(const auto & entry : _deviceList){
|
|
|
|
alive ? SSDPServer::sendAlive(entry) : SSDPServer::sendByeBye(entry);
|
|
|
|
}
|
2018-12-30 22:07:53 +01:00
|
|
|
}
|