2018-12-28 17:55:49 +01:00
# include "FlatBufferClient.h"
// qt
# include <QTcpSocket>
# include <QHostAddress>
# include <QTimer>
2018-12-30 22:07:53 +01:00
# include <QRgb>
2018-12-28 17:55:49 +01:00
2020-08-08 13:09:15 +02:00
FlatBufferClient : : FlatBufferClient ( QTcpSocket * socket , int timeout , QObject * parent )
2018-12-28 17:55:49 +01:00
: QObject ( parent )
, _log ( Logger : : getInstance ( " FLATBUFSERVER " ) )
, _socket ( socket )
2018-12-30 22:07:53 +01:00
, _clientAddress ( " @ " + socket - > peerAddress ( ) . toString ( ) )
2018-12-28 17:55:49 +01:00
, _timeoutTimer ( new QTimer ( this ) )
, _timeout ( timeout * 1000 )
, _priority ( )
{
// timer setup
_timeoutTimer - > setSingleShot ( true ) ;
_timeoutTimer - > setInterval ( _timeout ) ;
connect ( _timeoutTimer , & QTimer : : timeout , this , & FlatBufferClient : : forceClose ) ;
// connect socket signals
connect ( _socket , & QTcpSocket : : readyRead , this , & FlatBufferClient : : readyRead ) ;
connect ( _socket , & QTcpSocket : : disconnected , this , & FlatBufferClient : : disconnected ) ;
}
void FlatBufferClient : : readyRead ( )
{
_timeoutTimer - > start ( ) ;
_receiveBuffer + = _socket - > readAll ( ) ;
// check if we can read a header
while ( _receiveBuffer . size ( ) > = 4 )
{
uint32_t messageSize =
( ( _receiveBuffer [ 0 ] < < 24 ) & 0xFF000000 ) |
( ( _receiveBuffer [ 1 ] < < 16 ) & 0x00FF0000 ) |
( ( _receiveBuffer [ 2 ] < < 8 ) & 0x0000FF00 ) |
( ( _receiveBuffer [ 3 ] ) & 0x000000FF ) ;
// check if we can read a complete message
if ( ( uint32_t ) _receiveBuffer . size ( ) < messageSize + 4 ) return ;
2018-12-28 18:12:45 +01:00
// extract message only and remove header + msg from buffer :: QByteArray::remove() does not return the removed data
2020-03-01 15:37:06 +01:00
const QByteArray msg = _receiveBuffer . mid ( 4 , messageSize ) ;
2018-12-28 18:12:45 +01:00
_receiveBuffer . remove ( 0 , messageSize + 4 ) ;
2018-12-28 17:55:49 +01:00
2018-12-30 22:07:53 +01:00
const auto * msgData = reinterpret_cast < const uint8_t * > ( msg . constData ( ) ) ;
2018-12-28 17:55:49 +01:00
flatbuffers : : Verifier verifier ( msgData , messageSize ) ;
2018-12-30 22:07:53 +01:00
if ( hyperionnet : : VerifyRequestBuffer ( verifier ) )
2018-12-28 17:55:49 +01:00
{
2018-12-30 22:07:53 +01:00
auto message = hyperionnet : : GetRequest ( msgData ) ;
2018-12-28 17:55:49 +01:00
handleMessage ( message ) ;
continue ;
}
sendErrorReply ( " Unable to parse message " ) ;
}
}
void FlatBufferClient : : forceClose ( )
{
_socket - > close ( ) ;
}
void FlatBufferClient : : disconnected ( )
{
2019-02-03 14:36:57 +01:00
Debug ( _log , " Socket Closed " ) ;
2019-07-29 19:09:26 +02:00
_socket - > deleteLater ( ) ;
2019-08-02 21:12:13 +02:00
if ( _priority ! = 0 & & _priority > = 100 & & _priority < 200 )
emit clearGlobalInput ( _priority ) ;
2018-12-28 17:55:49 +01:00
emit clientDisconnected ( ) ;
}
2018-12-30 22:07:53 +01:00
void FlatBufferClient : : handleMessage ( const hyperionnet : : Request * req )
2018-12-28 17:55:49 +01:00
{
2018-12-30 22:07:53 +01:00
const void * reqPtr ;
if ( ( reqPtr = req - > command_as_Color ( ) ) ! = nullptr ) {
handleColorCommand ( static_cast < const hyperionnet : : Color * > ( reqPtr ) ) ;
} else if ( ( reqPtr = req - > command_as_Image ( ) ) ! = nullptr ) {
handleImageCommand ( static_cast < const hyperionnet : : Image * > ( reqPtr ) ) ;
} else if ( ( reqPtr = req - > command_as_Clear ( ) ) ! = nullptr ) {
handleClearCommand ( static_cast < const hyperionnet : : Clear * > ( reqPtr ) ) ;
} else if ( ( reqPtr = req - > command_as_Register ( ) ) ! = nullptr ) {
handleRegisterCommand ( static_cast < const hyperionnet : : Register * > ( reqPtr ) ) ;
} else {
sendErrorReply ( " Received invalid packet. " ) ;
2018-12-28 17:55:49 +01:00
}
}
2018-12-30 22:07:53 +01:00
void FlatBufferClient : : handleColorCommand ( const hyperionnet : : Color * colorReq )
2018-12-28 17:55:49 +01:00
{
// extract parameters
2018-12-30 22:07:53 +01:00
const int32_t rgbData = colorReq - > data ( ) ;
2020-02-26 18:54:56 +01:00
std : : vector < ColorRgb > color { ColorRgb { uint8_t ( qRed ( rgbData ) ) , uint8_t ( qGreen ( rgbData ) ) , uint8_t ( qBlue ( rgbData ) ) } } ;
2018-12-28 17:55:49 +01:00
2018-12-30 22:07:53 +01:00
// set output
2019-07-29 19:09:26 +02:00
emit setGlobalInputColor ( _priority , color , colorReq - > duration ( ) ) ;
2018-12-30 22:07:53 +01:00
// send reply
sendSuccessReply ( ) ;
}
2020-08-08 13:09:15 +02:00
void FlatBufferClient : : registationRequired ( int priority )
2019-07-29 19:09:26 +02:00
{
if ( _priority = = priority )
{
auto reply = hyperionnet : : CreateReplyDirect ( _builder , nullptr , - 1 , - 1 ) ;
_builder . Finish ( reply ) ;
// send reply
sendMessage ( ) ;
2020-03-01 15:37:06 +01:00
_builder . Clear ( ) ;
2019-07-29 19:09:26 +02:00
}
}
2018-12-30 22:07:53 +01:00
void FlatBufferClient : : handleRegisterCommand ( const hyperionnet : : Register * regReq )
{
2019-08-02 21:12:13 +02:00
if ( regReq - > priority ( ) < 100 | | regReq - > priority ( ) > = 200 )
{
2019-08-12 19:06:11 +02:00
Error ( _log , " Register request from client %s contains invalid priority %d. Valid priority for Flatbuffer connections is between 100 and 199. " , QSTRING_CSTR ( _clientAddress ) , regReq - > priority ( ) ) ;
2019-08-02 21:12:13 +02:00
sendErrorReply ( " The priority " + std : : to_string ( regReq - > priority ( ) ) + " is not in the priority range between 100 and 199. " ) ;
return ;
}
2018-12-30 22:07:53 +01:00
_priority = regReq - > priority ( ) ;
2019-07-29 19:09:26 +02:00
emit registerGlobalInput ( _priority , hyperion : : COMP_FLATBUFSERVER , regReq - > origin ( ) - > c_str ( ) + _clientAddress ) ;
2019-02-05 19:55:48 +01:00
auto reply = hyperionnet : : CreateReplyDirect ( _builder , nullptr , - 1 , ( _priority ? _priority : - 1 ) ) ;
_builder . Finish ( reply ) ;
// send reply
sendMessage ( ) ;
2020-03-01 15:37:06 +01:00
_builder . Clear ( ) ;
2018-12-30 22:07:53 +01:00
}
void FlatBufferClient : : handleImageCommand ( const hyperionnet : : Image * image )
{
// extract parameters
int duration = image - > duration ( ) ;
const void * reqPtr ;
if ( ( reqPtr = image - > data_as_RawImage ( ) ) ! = nullptr )
2018-12-28 17:55:49 +01:00
{
2018-12-30 22:07:53 +01:00
const auto * img = static_cast < const hyperionnet : : RawImage * > ( reqPtr ) ;
const auto & imageData = img - > data ( ) ;
const int width = img - > width ( ) ;
const int height = img - > height ( ) ;
2018-12-28 17:55:49 +01:00
2022-01-09 17:23:50 +01:00
if ( width < = 0 | | height < = 0 )
2018-12-30 22:07:53 +01:00
{
sendErrorReply ( " Size of image data does not match with the width and height " ) ;
return ;
}
2018-12-28 17:55:49 +01:00
2022-01-09 17:23:50 +01:00
// check consistency of the size of the received data
int channelCount = ( int ) imageData - > size ( ) / ( width * height ) ;
if ( channelCount ! = 3 & & channelCount ! = 4 )
{
sendErrorReply ( " Size of image data does not match with the width and height " ) ;
return ;
}
// create ImageRgb
Image < ColorRgb > imageRGB ( width , height ) ;
if ( channelCount = = 3 )
{
memmove ( imageRGB . memptr ( ) , imageData - > data ( ) , imageData - > size ( ) ) ;
}
if ( channelCount = = 4 )
{
for ( int source = 0 , destination = 0 ; source < width * height * static_cast < int > ( sizeof ( ColorRgb ) ) ; source + = sizeof ( ColorRgb ) , destination + = sizeof ( ColorRgba ) )
{
memmove ( ( uint8_t * ) imageRGB . memptr ( ) + source , imageData - > data ( ) + destination , sizeof ( ColorRgb ) ) ;
}
}
emit setGlobalInputImage ( _priority , imageRGB , duration ) ;
2022-05-29 17:47:08 +02:00
emit setBufferImage ( " FlatBuffer " , imageRGB ) ;
2018-12-30 22:07:53 +01:00
}
2018-12-28 17:55:49 +01:00
// send reply
sendSuccessReply ( ) ;
}
2018-12-30 22:07:53 +01:00
void FlatBufferClient : : handleClearCommand ( const hyperionnet : : Clear * clear )
{
// extract parameters
const int priority = clear - > priority ( ) ;
2020-02-26 18:54:56 +01:00
// Check if we are clearing ourselves.
if ( priority = = _priority ) {
_priority = - 1 ;
2018-12-30 22:07:53 +01:00
}
2020-02-26 18:54:56 +01:00
emit clearGlobalInput ( priority ) ;
2018-12-30 22:07:53 +01:00
sendSuccessReply ( ) ;
}
2018-12-28 17:55:49 +01:00
void FlatBufferClient : : handleNotImplemented ( )
{
sendErrorReply ( " Command not implemented " ) ;
}
void FlatBufferClient : : sendMessage ( )
{
auto size = _builder . GetSize ( ) ;
const uint8_t * buffer = _builder . GetBufferPointer ( ) ;
uint8_t sizeData [ ] = { uint8_t ( size > > 24 ) , uint8_t ( size > > 16 ) , uint8_t ( size > > 8 ) , uint8_t ( size ) } ;
_socket - > write ( ( const char * ) sizeData , sizeof ( sizeData ) ) ;
_socket - > write ( ( const char * ) buffer , size ) ;
_socket - > flush ( ) ;
}
void FlatBufferClient : : sendSuccessReply ( )
{
2018-12-30 22:07:53 +01:00
auto reply = hyperionnet : : CreateReplyDirect ( _builder ) ;
2018-12-28 17:55:49 +01:00
_builder . Finish ( reply ) ;
// send reply
sendMessage ( ) ;
2020-03-01 15:37:06 +01:00
_builder . Clear ( ) ;
2018-12-28 17:55:49 +01:00
}
void FlatBufferClient : : sendErrorReply ( const std : : string & error )
{
// create reply
2018-12-30 22:07:53 +01:00
auto reply = hyperionnet : : CreateReplyDirect ( _builder , error . c_str ( ) ) ;
2018-12-28 17:55:49 +01:00
_builder . Finish ( reply ) ;
// send reply
sendMessage ( ) ;
2020-03-01 15:37:06 +01:00
_builder . Clear ( ) ;
2018-12-28 17:55:49 +01:00
}