diff --git a/deflect/MessageHeader.h b/deflect/MessageHeader.h index c94f5a0..e6aab26 100644 --- a/deflect/MessageHeader.h +++ b/deflect/MessageHeader.h @@ -66,7 +66,8 @@ enum MessageType MESSAGE_TYPE_BIND_EVENTS_REPLY = 8, MESSAGE_TYPE_EVENT = 9, MESSAGE_TYPE_QUIT = 12, - MESSAGE_TYPE_SIZE_HINTS = 13 + MESSAGE_TYPE_SIZE_HINTS = 13, + MESSAGE_TYPE_DATA = 14 }; #define MESSAGE_HEADER_URI_LENGTH 64 diff --git a/deflect/Server.cpp b/deflect/Server.cpp index 8f9a463..f6d0b9f 100644 --- a/deflect/Server.cpp +++ b/deflect/Server.cpp @@ -138,6 +138,8 @@ void Server::incomingConnection( const qintptr socketHandle ) this, &Server::registerToEvents ); connect( worker, &ServerWorker::receivedSizeHints, this, &Server::receivedSizeHints ); + connect( worker, &ServerWorker::receivedData, + this, &Server::receivedData ); connect( this, &Server::_pixelStreamerClosed, worker, &ServerWorker::closeConnection ); connect( this, &Server::_eventRegistrationReply, diff --git a/deflect/Server.h b/deflect/Server.h index ee83061..40590e5 100644 --- a/deflect/Server.h +++ b/deflect/Server.h @@ -83,6 +83,8 @@ class DEFLECT_API Server : public QTcpServer void receivedSizeHints( QString uri, deflect::SizeHints hints ); + void receivedData( QString uri, QByteArray data ); + public slots: void onPixelStreamerClosed( QString uri ); void onEventRegistrationReply( QString uri, bool success ); diff --git a/deflect/ServerWorker.cpp b/deflect/ServerWorker.cpp index 2352bfe..e15acb9 100644 --- a/deflect/ServerWorker.cpp +++ b/deflect/ServerWorker.cpp @@ -242,6 +242,10 @@ void ServerWorker::_handleMessage( const MessageHeader& messageHeader, break; } + case MESSAGE_TYPE_DATA: + emit receivedData( _streamId, byteArray ); + break; + case MESSAGE_TYPE_BIND_EVENTS: case MESSAGE_TYPE_BIND_EVENTS_EX: if( _registeredToEvents ) diff --git a/deflect/ServerWorker.h b/deflect/ServerWorker.h index d127219..7cc0b03 100644 --- a/deflect/ServerWorker.h +++ b/deflect/ServerWorker.h @@ -81,6 +81,8 @@ public slots: void receivedSizeHints( QString uri, deflect::SizeHints hints ); + void receivedData( QString uri, QByteArray data ); + void connectionClosed(); /** @internal */ diff --git a/deflect/Stream.cpp b/deflect/Stream.cpp index 9496c6d..a3cf2e6 100644 --- a/deflect/Stream.cpp +++ b/deflect/Stream.cpp @@ -189,4 +189,9 @@ void Stream::sendSizeHints( const SizeHints& hints ) _impl->sendSizeHints( hints ); } +bool Stream::sendData( const char* data, const size_t count ) +{ + return _impl->send( QByteArray::fromRawData( data, count )); +} + } diff --git a/deflect/Stream.h b/deflect/Stream.h index a04c5c8..54c260a 100644 --- a/deflect/Stream.h +++ b/deflect/Stream.h @@ -259,6 +259,16 @@ class Stream */ DEFLECT_API void sendSizeHints( const SizeHints& hints ); + /** + * Send data to the Server. + * + * @param data the pointer to the data buffer. + * @param count the number of bytes to send. + * @return true if the data could be sent, false otherwise + * @version 1.3 + */ + DEFLECT_API bool sendData( const char* data, size_t count ); + private: Stream( const Stream& ) = delete; const Stream& operator = ( const Stream& ) = delete; diff --git a/deflect/StreamPrivate.cpp b/deflect/StreamPrivate.cpp index 706cc65..641c3d4 100644 --- a/deflect/StreamPrivate.cpp +++ b/deflect/StreamPrivate.cpp @@ -177,4 +177,10 @@ bool StreamPrivate::sendSizeHints( const SizeHints& hints ) return socket.send( mh, message ); } +bool StreamPrivate::send( const QByteArray data ) +{ + const MessageHeader mh( MESSAGE_TYPE_DATA, data.size(), id ); + return socket.send( mh, data ); +} + } diff --git a/deflect/StreamPrivate.h b/deflect/StreamPrivate.h index da776cc..c7ecc59 100644 --- a/deflect/StreamPrivate.h +++ b/deflect/StreamPrivate.h @@ -108,6 +108,9 @@ class StreamPrivate /** @sa Stream::sendSizeHints */ bool sendSizeHints( const SizeHints& hints ); + /** Send a user-defined block of data to the server. */ + bool send( QByteArray data ); + /** The stream identifier. */ const std::string id; diff --git a/doc/Changelog.md b/doc/Changelog.md index e6a9361..5870633 100644 --- a/doc/Changelog.md +++ b/doc/Changelog.md @@ -5,6 +5,9 @@ Changelog {#Changelog} ### 0.12.0 (git master) +* [119](https://github.com/BlueBrain/Deflect/pull/119): + Added deflect::Stream::sendData() to allow sending user-defined information + to the deflect::Server. * [118](https://github.com/BlueBrain/Deflect/pull/118): New "pan" event for multi-finger pan gestures. * [117](https://github.com/BlueBrain/Deflect/pull/117): diff --git a/tests/cpp/ServerTests.cpp b/tests/cpp/ServerTests.cpp index 87eb624..6ac4ca6 100644 --- a/tests/cpp/ServerTests.cpp +++ b/tests/cpp/ServerTests.cpp @@ -174,3 +174,58 @@ BOOST_AUTO_TEST_CASE( testRegisterForEventReceivedByServer ) } BOOST_CHECK( !"reachable" ); } + +BOOST_AUTO_TEST_CASE( testDataReceivedByServer ) +{ + QThread serverThread; + deflect::Server* server = new deflect::Server( 0 /* OS-chosen port */ ); + server->moveToThread( &serverThread ); + serverThread.connect( &serverThread, &QThread::finished, + server, &deflect::Server::deleteLater ); + serverThread.start(); + + QWaitCondition received; + QMutex mutex; + + QString streamId; + std::string receivedData; + const auto sentData = std::string{ "Hello World!" }; + + bool receivedState = false; + server->connect( server, &deflect::Server::receivedData, + [&]( const QString id, QByteArray data ) + { + streamId = id; + receivedData = QString( data ).toStdString(); + mutex.lock(); + receivedState = true; + received.wakeAll(); + mutex.unlock(); + }); + + { + deflect::Stream stream( testStreamId.toStdString(), "localhost", + server->serverPort( )); + BOOST_REQUIRE( stream.isConnected( )); + stream.sendData( sentData.data(), sentData.size( )); + } + + for( size_t i = 0; i < 20; ++i ) + { + mutex.lock(); + received.wait( &mutex, 100 /*ms*/ ); + if( receivedState ) + { + BOOST_CHECK_EQUAL( streamId.toStdString(), + testStreamId.toStdString( )); + BOOST_CHECK_EQUAL( receivedData, sentData ); + + serverThread.quit(); + serverThread.wait(); + mutex.unlock(); + return; + } + mutex.unlock(); + } + BOOST_CHECK( !"reachable" ); +}