2016-02-16 14:59:31 +01:00
// STL includes
2016-02-16 15:56:20 +01:00
# include <stdexcept>
2016-02-16 14:59:31 +01:00
2019-02-03 14:36:57 +01:00
// project includes
2022-01-07 14:47:51 +01:00
# include <forwarder/MessageForwarder.h>
2016-02-15 18:25:18 +01:00
2019-02-03 14:36:57 +01:00
// hyperion includes
2018-12-27 23:11:32 +01:00
# include <hyperion/Hyperion.h>
2016-02-15 18:25:18 +01:00
2019-02-03 14:36:57 +01:00
// utils includes
# include <utils/Logger.h>
2021-11-17 21:30:43 +01:00
# include <utils/NetUtils.h>
2019-02-03 14:36:57 +01:00
// qt includes
# include <QTcpServer>
# include <QTcpSocket>
2021-11-17 21:30:43 +01:00
# include <QHostInfo>
# include <QNetworkInterface>
2019-02-03 14:36:57 +01:00
# include <flatbufserver/FlatBufferConnection.h>
2021-11-17 21:30:43 +01:00
MessageForwarder : : MessageForwarder ( Hyperion * hyperion )
: _hyperion ( hyperion )
2022-01-22 17:48:03 +01:00
, _log ( nullptr )
2019-02-03 14:36:57 +01:00
, _muxer ( _hyperion - > getMuxerInstance ( ) )
, _forwarder_enabled ( true )
, _priority ( 140 )
2016-02-15 18:25:18 +01:00
{
2022-01-22 17:48:03 +01:00
QString subComponent = hyperion - > property ( " instance " ) . toString ( ) ;
_log = Logger : : getInstance ( " NETFORWARDER " , subComponent ) ;
2018-12-27 23:11:32 +01:00
// get settings updates
connect ( _hyperion , & Hyperion : : settingsChanged , this , & MessageForwarder : : handleSettingsUpdate ) ;
2019-02-03 14:36:57 +01:00
// component changes
2020-02-26 18:54:56 +01:00
connect ( _hyperion , & Hyperion : : compStateChangeRequest , this , & MessageForwarder : : handleCompStateChangeRequest ) ;
2019-02-03 14:36:57 +01:00
// connect with Muxer visible priority changes
connect ( _muxer , & PriorityMuxer : : visiblePriorityChanged , this , & MessageForwarder : : handlePriorityChanges ) ;
// init
handleSettingsUpdate ( settings : : NETFORWARD , _hyperion - > getSetting ( settings : : NETFORWARD ) ) ;
2016-02-15 18:25:18 +01:00
}
MessageForwarder : : ~ MessageForwarder ( )
{
2019-02-03 14:36:57 +01:00
while ( ! _forwardClients . isEmpty ( ) )
2021-11-17 21:30:43 +01:00
{
2019-02-03 14:36:57 +01:00
delete _forwardClients . takeFirst ( ) ;
2021-11-17 21:30:43 +01:00
}
2016-02-15 18:25:18 +01:00
}
2021-11-17 21:30:43 +01:00
void MessageForwarder : : handleSettingsUpdate ( settings : : type type , const QJsonDocument & config )
2018-12-27 23:11:32 +01:00
{
2021-11-17 21:30:43 +01:00
if ( type = = settings : : NETFORWARD )
2018-12-27 23:11:32 +01:00
{
// clear the current targets
2021-11-17 21:30:43 +01:00
_jsonTargets . clear ( ) ;
_flatbufferTargets . clear ( ) ;
2019-02-03 14:36:57 +01:00
while ( ! _forwardClients . isEmpty ( ) )
2021-11-17 21:30:43 +01:00
{
2019-02-03 14:36:57 +01:00
delete _forwardClients . takeFirst ( ) ;
2021-11-17 21:30:43 +01:00
}
2019-02-03 14:36:57 +01:00
2018-12-27 23:11:32 +01:00
// build new one
2021-11-17 21:30:43 +01:00
const QJsonObject & obj = config . object ( ) ;
if ( ! obj [ " json " ] . isNull ( ) )
2018-12-27 23:11:32 +01:00
{
2021-11-17 21:30:43 +01:00
const QJsonArray & addr = obj [ " json " ] . toArray ( ) ;
2018-12-27 23:11:32 +01:00
for ( const auto & entry : addr )
{
2021-11-17 21:30:43 +01:00
addJsonTarget ( entry . toObject ( ) ) ;
2018-12-27 23:11:32 +01:00
}
}
2021-11-17 21:30:43 +01:00
if ( ! obj [ " flat " ] . isNull ( ) )
2018-12-27 23:11:32 +01:00
{
2021-11-17 21:30:43 +01:00
const QJsonArray & addr = obj [ " flat " ] . toArray ( ) ;
2018-12-27 23:11:32 +01:00
for ( const auto & entry : addr )
{
2021-11-17 21:30:43 +01:00
addFlatbufferTarget ( entry . toObject ( ) ) ;
2018-12-27 23:11:32 +01:00
}
}
2019-02-03 14:36:57 +01:00
2021-11-17 21:30:43 +01:00
bool isForwarderEnabledinSettings = obj [ " enable " ] . toBool ( false ) ;
if ( ! _jsonTargets . isEmpty ( ) & & isForwarderEnabledinSettings & & _forwarder_enabled )
2019-02-03 14:36:57 +01:00
{
2021-11-17 21:30:43 +01:00
for ( const auto & targetHost : qAsConst ( _jsonTargets ) )
{
InfoIf ( isForwarderEnabledinSettings , _log , " Forwarding now to JSON-target host: %s port: %u " , QSTRING_CSTR ( targetHost . host . toString ( ) ) , targetHost . port ) ;
}
2019-02-03 14:36:57 +01:00
connect ( _hyperion , & Hyperion : : forwardJsonMessage , this , & MessageForwarder : : forwardJsonMessage , Qt : : UniqueConnection ) ;
2021-11-17 21:30:43 +01:00
}
else if ( _jsonTargets . isEmpty ( ) | | ! isForwarderEnabledinSettings | | ! _forwarder_enabled )
{
disconnect ( _hyperion , & Hyperion : : forwardJsonMessage , nullptr , nullptr ) ;
}
2019-02-03 14:36:57 +01:00
2021-11-17 21:30:43 +01:00
if ( ! _flatbufferTargets . isEmpty ( ) & & isForwarderEnabledinSettings & & _forwarder_enabled )
2019-02-03 14:36:57 +01:00
{
2021-11-17 21:30:43 +01:00
for ( const auto & targetHost : qAsConst ( _flatbufferTargets ) )
{
InfoIf ( isForwarderEnabledinSettings , _log , " Forwarding now to Flatbuffer-target host: %s port: %u " , QSTRING_CSTR ( targetHost . host . toString ( ) ) , targetHost . port ) ;
}
2019-08-24 21:12:53 +02:00
}
2021-11-17 21:30:43 +01:00
else if ( _flatbufferTargets . isEmpty ( ) | | ! isForwarderEnabledinSettings | | ! _forwarder_enabled )
2019-07-02 19:06:36 +02:00
{
2021-11-17 21:30:43 +01:00
disconnect ( _hyperion , & Hyperion : : forwardSystemProtoMessage , nullptr , nullptr ) ;
disconnect ( _hyperion , & Hyperion : : forwardV4lProtoMessage , nullptr , nullptr ) ;
2019-07-02 19:06:36 +02:00
}
2019-02-03 14:36:57 +01:00
2018-12-27 23:11:32 +01:00
// update comp state
2021-11-17 21:30:43 +01:00
_hyperion - > setNewComponentState ( hyperion : : COMP_FORWARDER , isForwarderEnabledinSettings ) ;
2018-12-27 23:11:32 +01:00
}
}
2016-02-15 18:25:18 +01:00
2020-08-08 13:09:15 +02:00
void MessageForwarder : : handleCompStateChangeRequest ( hyperion : : Components component , bool enable )
2019-02-03 14:36:57 +01:00
{
if ( component = = hyperion : : COMP_FORWARDER & & _forwarder_enabled ! = enable )
{
_forwarder_enabled = enable ;
handleSettingsUpdate ( settings : : NETFORWARD , _hyperion - > getSetting ( settings : : NETFORWARD ) ) ;
2019-02-05 19:55:48 +01:00
Info ( _log , " Forwarder change state to %s " , ( _forwarder_enabled ? " enabled " : " disabled " ) ) ;
2020-02-26 18:54:56 +01:00
_hyperion - > setNewComponentState ( component , _forwarder_enabled ) ;
2019-02-03 14:36:57 +01:00
}
}
2020-08-08 13:09:15 +02:00
void MessageForwarder : : handlePriorityChanges ( quint8 priority )
2019-02-03 14:36:57 +01:00
{
const QJsonObject obj = _hyperion - > getSetting ( settings : : NETFORWARD ) . object ( ) ;
if ( priority ! = 0 & & _forwarder_enabled & & obj [ " enable " ] . toBool ( ) )
{
2019-07-02 19:06:36 +02:00
hyperion : : Components activeCompId = _hyperion - > getPriorityInfo ( priority ) . componentId ;
if ( activeCompId = = hyperion : : COMP_GRABBER | | activeCompId = = hyperion : : COMP_V4L )
2019-02-03 14:36:57 +01:00
{
2021-11-17 21:30:43 +01:00
if ( ! obj [ " flat " ] . isNull ( ) )
2019-02-03 14:36:57 +01:00
{
2021-11-17 21:30:43 +01:00
const QJsonArray & addr = obj [ " flat " ] . toArray ( ) ;
2019-02-03 14:36:57 +01:00
for ( const auto & entry : addr )
{
2021-11-17 21:30:43 +01:00
addFlatbufferTarget ( entry . toObject ( ) ) ;
2019-02-03 14:36:57 +01:00
}
}
2019-07-02 19:06:36 +02:00
2021-11-17 21:30:43 +01:00
switch ( activeCompId )
2019-07-02 19:06:36 +02:00
{
2021-11-17 21:30:43 +01:00
case hyperion : : COMP_GRABBER :
{
disconnect ( _hyperion , & Hyperion : : forwardV4lProtoMessage , nullptr , nullptr ) ;
connect ( _hyperion , & Hyperion : : forwardSystemProtoMessage , this , & MessageForwarder : : forwardFlatbufferMessage , Qt : : UniqueConnection ) ;
}
break ;
case hyperion : : COMP_V4L :
{
disconnect ( _hyperion , & Hyperion : : forwardSystemProtoMessage , nullptr , nullptr ) ;
connect ( _hyperion , & Hyperion : : forwardV4lProtoMessage , this , & MessageForwarder : : forwardFlatbufferMessage , Qt : : UniqueConnection ) ;
}
break ;
default :
{
disconnect ( _hyperion , & Hyperion : : forwardSystemProtoMessage , nullptr , nullptr ) ;
disconnect ( _hyperion , & Hyperion : : forwardV4lProtoMessage , nullptr , nullptr ) ;
}
2019-07-02 19:06:36 +02:00
}
2019-02-03 14:36:57 +01:00
}
else
2019-07-02 19:06:36 +02:00
{
2021-11-17 21:30:43 +01:00
disconnect ( _hyperion , & Hyperion : : forwardSystemProtoMessage , nullptr , nullptr ) ;
disconnect ( _hyperion , & Hyperion : : forwardV4lProtoMessage , nullptr , nullptr ) ;
2019-07-02 19:06:36 +02:00
}
2019-02-03 14:36:57 +01:00
}
}
2021-11-17 21:30:43 +01:00
void MessageForwarder : : addJsonTarget ( const QJsonObject & targetConfig )
2016-02-15 18:25:18 +01:00
{
2021-11-17 21:30:43 +01:00
TargetHost targetHost ;
2016-02-15 20:53:03 +01:00
2021-11-17 21:30:43 +01:00
QString config_host = targetConfig [ " host " ] . toString ( ) ;
if ( NetUtils : : resolveHostAddress ( _log , config_host , targetHost . host ) )
2018-12-27 23:11:32 +01:00
{
2021-11-17 21:30:43 +01:00
int config_port = targetConfig [ " port " ] . toInt ( ) ;
if ( NetUtils : : isValidPort ( _log , config_port , config_host ) )
{
targetHost . port = static_cast < quint16 > ( config_port ) ;
2018-12-27 23:11:32 +01:00
2021-11-17 21:30:43 +01:00
// verify loop with JSON-server
const QJsonObject & obj = _hyperion - > getSetting ( settings : : JSONSERVER ) . object ( ) ;
if ( ( QNetworkInterface : : allAddresses ( ) . indexOf ( targetHost . host ) ! = - 1 ) & & targetHost . port = = static_cast < quint16 > ( obj [ " port " ] . toInt ( ) ) )
{
Error ( _log , " Loop between JSON-Server and Forwarder! Configuration for host: %s, port: %d is ignored. " , QSTRING_CSTR ( config_host ) , config_port ) ;
}
else
{
if ( _forwarder_enabled )
{
if ( _jsonTargets . indexOf ( targetHost ) = = - 1 )
{
Info ( _log , " JSON-Forwarder settings: Adding target host: %s port: %u " , QSTRING_CSTR ( targetHost . host . toString ( ) ) , targetHost . port ) ;
_jsonTargets < < targetHost ;
}
else
{
Warning ( _log , " JSON Forwarder settings: Duplicate target host configuration! Configuration for host: %s, port: %d is ignored. " , QSTRING_CSTR ( targetHost . host . toString ( ) ) , targetHost . port ) ;
}
}
2016-02-15 20:53:03 +01:00
2021-11-17 21:30:43 +01:00
}
}
}
2016-02-15 18:25:18 +01:00
}
2021-11-17 21:30:43 +01:00
void MessageForwarder : : addFlatbufferTarget ( const QJsonObject & targetConfig )
2016-02-15 18:25:18 +01:00
{
2021-11-17 21:30:43 +01:00
TargetHost targetHost ;
2016-02-15 20:53:03 +01:00
2021-11-17 21:30:43 +01:00
QString config_host = targetConfig [ " host " ] . toString ( ) ;
if ( NetUtils : : resolveHostAddress ( _log , config_host , targetHost . host ) )
2018-12-27 23:11:32 +01:00
{
2021-11-17 21:30:43 +01:00
int config_port = targetConfig [ " port " ] . toInt ( ) ;
if ( NetUtils : : isValidPort ( _log , config_port , config_host ) )
{
targetHost . port = static_cast < quint16 > ( config_port ) ;
2019-02-03 14:36:57 +01:00
2021-11-17 21:30:43 +01:00
// verify loop with Flatbuffer-server
const QJsonObject & obj = _hyperion - > getSetting ( settings : : FLATBUFSERVER ) . object ( ) ;
if ( ( QNetworkInterface : : allAddresses ( ) . indexOf ( targetHost . host ) ! = - 1 ) & & targetHost . port = = static_cast < quint16 > ( obj [ " port " ] . toInt ( ) ) )
{
Error ( _log , " Loop between Flatbuffer-Server and Forwarder! Configuration for host: %s, port: %d is ignored. " , QSTRING_CSTR ( config_host ) , config_port ) ;
}
else
{
if ( _forwarder_enabled )
{
if ( _flatbufferTargets . indexOf ( targetHost ) = = - 1 )
{
Info ( _log , " Flatbuffer-Forwarder settings: Adding target host: %s port: %u " , QSTRING_CSTR ( targetHost . host . toString ( ) ) , targetHost . port ) ;
_flatbufferTargets < < targetHost ;
FlatBufferConnection * flatbuf = new FlatBufferConnection ( " Forwarder " , targetHost . host . toString ( ) , _priority , false , targetHost . port ) ;
_forwardClients < < flatbuf ;
}
else
{
Warning ( _log , " Flatbuffer Forwarder settings: Duplicate target host configuration! Configuration for host: %s, port: %d is ignored. " , QSTRING_CSTR ( targetHost . host . toString ( ) ) , targetHost . port ) ;
}
}
}
}
2019-02-03 14:36:57 +01:00
}
}
2021-11-17 21:30:43 +01:00
void MessageForwarder : : forwardJsonMessage ( const QJsonObject & message )
2019-02-03 14:36:57 +01:00
{
if ( _forwarder_enabled )
{
QTcpSocket client ;
2021-11-17 21:30:43 +01:00
for ( const auto & targetHost : qAsConst ( _jsonTargets ) )
2019-02-03 14:36:57 +01:00
{
2021-11-17 21:30:43 +01:00
client . connectToHost ( targetHost . host , targetHost . port ) ;
if ( client . waitForConnected ( 500 ) )
2019-02-03 14:36:57 +01:00
{
2021-11-17 21:30:43 +01:00
sendJsonMessage ( message , & client ) ;
2019-02-03 14:36:57 +01:00
client . close ( ) ;
}
}
}
2016-02-15 20:53:03 +01:00
}
2016-02-19 13:31:08 +01:00
2021-11-17 21:30:43 +01:00
void MessageForwarder : : forwardFlatbufferMessage ( const QString & /*name*/ , const Image < ColorRgb > & image )
2016-02-19 13:31:08 +01:00
{
2019-02-03 14:36:57 +01:00
if ( _forwarder_enabled )
{
2021-11-17 21:30:43 +01:00
for ( int i = 0 ; i < _forwardClients . size ( ) ; i + + )
{
2019-02-03 14:36:57 +01:00
_forwardClients . at ( i ) - > setImage ( image ) ;
2021-11-17 21:30:43 +01:00
}
2019-02-03 14:36:57 +01:00
}
2016-02-19 13:31:08 +01:00
}
2016-09-07 20:10:37 +02:00
2021-11-17 21:30:43 +01:00
void MessageForwarder : : sendJsonMessage ( const QJsonObject & message , QTcpSocket * socket )
2016-09-07 20:10:37 +02:00
{
2019-02-03 14:36:57 +01:00
// for hyperion classic compatibility
QJsonObject jsonMessage = message ;
if ( jsonMessage . contains ( " tan " ) & & jsonMessage [ " tan " ] . isNull ( ) )
2021-11-17 21:30:43 +01:00
{
2019-02-03 14:36:57 +01:00
jsonMessage [ " tan " ] = 100 ;
2021-11-17 21:30:43 +01:00
}
2019-02-03 14:36:57 +01:00
// serialize message
QJsonDocument writer ( jsonMessage ) ;
QByteArray serializedMessage = writer . toJson ( QJsonDocument : : Compact ) + " \n " ;
// write message
socket - > write ( serializedMessage ) ;
if ( ! socket - > waitForBytesWritten ( ) )
{
Debug ( _log , " Error while writing data to host " ) ;
return ;
}
// read reply data
QByteArray serializedReply ;
while ( ! serializedReply . contains ( ' \n ' ) )
{
// receive reply
if ( ! socket - > waitForReadyRead ( ) )
{
Debug ( _log , " Error while writing data from host " ) ;
return ;
}
serializedReply + = socket - > readAll ( ) ;
}
// parse reply data
QJsonParseError error ;
2021-11-17 21:30:43 +01:00
QJsonDocument : : fromJson ( serializedReply , & error ) ;
2019-02-03 14:36:57 +01:00
if ( error . error ! = QJsonParseError : : NoError )
{
Error ( _log , " Error while parsing reply: invalid json " ) ;
return ;
}
2016-09-07 20:10:37 +02:00
}
2021-11-17 21:30:43 +01:00