diff --git a/include/flatbufserver/FlatBufferConnection.h b/include/flatbufserver/FlatBufferConnection.h index 736db88b6..e9265b731 100644 --- a/include/flatbufserver/FlatBufferConnection.h +++ b/include/flatbufserver/FlatBufferConnection.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -19,6 +20,8 @@ namespace hyperhdrnet struct Reply; } +#define HYPERHDR_DOMAIN_SERVER QStringLiteral("hyperhdr-domain") + /// /// Connection class to setup an connection to the hyperhdr server and execute commands. /// @@ -113,22 +116,22 @@ private slots: private: /// The TCP-Socket with the connection to the server - QTcpSocket _socket; - - QString _origin; - int _priority; + QTcpSocket* _socket; + QLocalSocket* _domain; + QString _origin; + int _priority; /// Host address - QString _host; + QString _host; /// Host port - uint16_t _port; + uint16_t _port; /// buffer for reply - QByteArray _receiveBuffer; - - QTimer _timer; - QAbstractSocket::SocketState _prevSocketState; + QByteArray _receiveBuffer; + QTimer _timer; + QAbstractSocket::SocketState _prevSocketState; + QLocalSocket::LocalSocketState _prevLocalState; Logger* _log; flatbuffers::FlatBufferBuilder _builder; diff --git a/include/flatbufserver/FlatBufferServer.h b/include/flatbufserver/FlatBufferServer.h index a2e74adee..0be8d32f4 100644 --- a/include/flatbufserver/FlatBufferServer.h +++ b/include/flatbufserver/FlatBufferServer.h @@ -9,9 +9,11 @@ class BonjourServiceRegister; class QTcpServer; +class QLocalServer; class FlatBufferClient; class NetOrigin; +#define HYPERHDR_DOMAIN_SERVER QStringLiteral("hyperhdr-domain") /// /// @brief A TcpServer to receive images of different formats with Google Flatbuffer @@ -75,13 +77,17 @@ private slots: /// void loadLutFile(); + void setupClient(FlatBufferClient* client); + private: - QTcpServer* _server; - NetOrigin* _netOrigin; - Logger* _log; - int _timeout; - quint16 _port; + QTcpServer* _server; + QLocalServer* _domain; + NetOrigin* _netOrigin; + Logger* _log; + int _timeout; + quint16 _port; + const QJsonDocument _config; BonjourServiceRegister* _serviceRegister = nullptr; diff --git a/sources/base/MessageForwarder.cpp b/sources/base/MessageForwarder.cpp index ead056b0d..020a09944 100644 --- a/sources/base/MessageForwarder.cpp +++ b/sources/base/MessageForwarder.cpp @@ -254,27 +254,30 @@ void MessageForwarder::addJsonSlave(const QString& slave) void MessageForwarder::addFlatbufferSlave(const QString& slave) { - QStringList parts = slave.split(":"); - if (parts.size() != 2) + if (slave != HYPERHDR_DOMAIN_SERVER) { - Error(_log, "Unable to parse address (%s)", QSTRING_CSTR(slave)); - return; - } + QStringList parts = slave.split(":"); + if (parts.size() != 2) + { + Error(_log, "Unable to parse address (%s)", QSTRING_CSTR(slave)); + return; + } - bool ok; - parts[1].toUShort(&ok); - if (!ok) - { - Error(_log, "Unable to parse port number (%s)", QSTRING_CSTR(parts[1])); - return; - } + bool ok; + parts[1].toUShort(&ok); + if (!ok) + { + Error(_log, "Unable to parse port number (%s)", QSTRING_CSTR(parts[1])); + return; + } - // verify loop with flatbufserver - const QJsonObject& obj = _hyperhdr->getSetting(settings::type::FLATBUFSERVER).object(); - if (QHostAddress(parts[0]) == QHostAddress::LocalHost && parts[1].toInt() == obj["port"].toInt()) - { - Error(_log, "Loop between Flatbuffer Server and Forwarder! (%s)", QSTRING_CSTR(slave)); - return; + // verify loop with flatbufserver + const QJsonObject& obj = _hyperhdr->getSetting(settings::type::FLATBUFSERVER).object(); + if (QHostAddress(parts[0]) == QHostAddress::LocalHost && parts[1].toInt() == obj["port"].toInt()) + { + Error(_log, "Loop between Flatbuffer Server and Forwarder! (%s)", QSTRING_CSTR(slave)); + return; + } } if (_forwarder_enabled && !_flatSlaves.contains(slave)) diff --git a/sources/flatbufserver/FlatBufferClient.cpp b/sources/flatbufserver/FlatBufferClient.cpp index 3816884bb..9f4af1981 100644 --- a/sources/flatbufserver/FlatBufferClient.cpp +++ b/sources/flatbufserver/FlatBufferClient.cpp @@ -2,6 +2,7 @@ // qt #include +#include #include #include #include @@ -9,32 +10,47 @@ // util includes #include -FlatBufferClient::FlatBufferClient(QTcpSocket* socket, int timeout, int hdrToneMappingEnabled, uint8_t* lutBuffer, QObject* parent) +FlatBufferClient::FlatBufferClient(QTcpSocket* socket, QLocalSocket* domain, int timeout, int hdrToneMappingEnabled, uint8_t* lutBuffer, QObject* parent) : QObject(parent) , _log(Logger::getInstance("FLATBUFSERVER")) , _socket(socket) - , _clientAddress("@" + socket->peerAddress().toString()) + , _domain(domain) + , _clientAddress("@LocalSocket") , _timeoutTimer(new QTimer(this)) , _timeout(timeout * 1000) , _priority() , _hdrToneMappingMode(hdrToneMappingEnabled) , _lutBuffer(lutBuffer) { + if (_socket != nullptr) + _clientAddress = "@" + _socket->peerAddress().toString(); + // 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); + if (_socket != nullptr) + { + connect(_socket, &QTcpSocket::readyRead, this, &FlatBufferClient::readyRead); + connect(_socket, &QTcpSocket::disconnected, this, &FlatBufferClient::disconnected); + } + else if (_domain != nullptr) + { + connect(_domain, &QLocalSocket::readyRead, this, &FlatBufferClient::readyRead); + connect(_domain, &QLocalSocket::disconnected, this, &FlatBufferClient::disconnected); + } } void FlatBufferClient::readyRead() { _timeoutTimer->start(); - _receiveBuffer += _socket->readAll(); + if (_socket != nullptr) + _receiveBuffer += _socket->readAll(); + else if (_domain != nullptr) + _receiveBuffer += _domain->readAll(); // check if we can read a header while (_receiveBuffer.size() >= 4) @@ -67,7 +83,10 @@ void FlatBufferClient::readyRead() void FlatBufferClient::forceClose() { - _socket->close(); + if (_socket != nullptr) + _socket->close(); + if (_domain != nullptr) + _domain->close(); } void FlatBufferClient::setHdrToneMappingEnabled(int mode, uint8_t* lutBuffer) @@ -79,7 +98,12 @@ void FlatBufferClient::setHdrToneMappingEnabled(int mode, uint8_t* lutBuffer) void FlatBufferClient::disconnected() { Debug(_log, "Socket Closed"); - _socket->deleteLater(); + + if (_socket != nullptr) + _socket->deleteLater(); + if (_domain != nullptr) + _domain->deleteLater(); + if (_priority != 0 && _priority >= 100 && _priority < 200) emit clearGlobalInput(_priority); @@ -212,9 +236,19 @@ 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(); + + if (_socket != nullptr) + { + _socket->write((const char*)sizeData, sizeof(sizeData)); + _socket->write((const char*)buffer, size); + _socket->flush(); + } + else if (_domain != nullptr) + { + _domain->write((const char*)sizeData, sizeof(sizeData)); + _domain->write((const char*)buffer, size); + _domain->flush(); + } } void FlatBufferClient::sendSuccessReply() diff --git a/sources/flatbufserver/FlatBufferClient.h b/sources/flatbufserver/FlatBufferClient.h index bb5bdd9a3..ddac6b195 100644 --- a/sources/flatbufserver/FlatBufferClient.h +++ b/sources/flatbufserver/FlatBufferClient.h @@ -11,6 +11,7 @@ #include "hyperhdr_request_generated.h" class QTcpSocket; +class QLocalSocket; class QTimer; /// @@ -26,7 +27,7 @@ class FlatBufferClient : public QObject /// @param timeout The timeout when a client is automatically disconnected and the priority unregistered /// @param parent The parent /// - explicit FlatBufferClient(QTcpSocket* socket, int timeout, int hdrToneMappingEnabled, uint8_t* lutBuffer, QObject* parent = nullptr); + explicit FlatBufferClient(QTcpSocket* socket, QLocalSocket* domain, int timeout, int hdrToneMappingEnabled, uint8_t* lutBuffer, QObject* parent = nullptr); signals: /// @@ -134,12 +135,13 @@ private slots: void sendErrorReply(const std::string& error); private: - Logger* _log; - QTcpSocket* _socket; - const QString _clientAddress; - QTimer* _timeoutTimer; - int _timeout; - int _priority; + Logger* _log; + QTcpSocket* _socket; + QLocalSocket* _domain; + QString _clientAddress; + QTimer* _timeoutTimer; + int _timeout; + int _priority; QByteArray _receiveBuffer; diff --git a/sources/flatbufserver/FlatBufferConnection.cpp b/sources/flatbufserver/FlatBufferConnection.cpp index d3924bd4a..5441c66a7 100644 --- a/sources/flatbufserver/FlatBufferConnection.cpp +++ b/sources/flatbufserver/FlatBufferConnection.cpp @@ -13,34 +13,58 @@ #include "hyperhdr_request_generated.h" FlatBufferConnection::FlatBufferConnection(const QString& origin, const QString& address, int priority, bool skipReply) - : _socket() + : _socket((address == HYPERHDR_DOMAIN_SERVER) ? nullptr : new QTcpSocket()) + , _domain((address == HYPERHDR_DOMAIN_SERVER) ? new QLocalSocket() : nullptr) , _origin(origin) , _priority(priority) , _prevSocketState(QAbstractSocket::UnconnectedState) + , _prevLocalState(QLocalSocket::UnconnectedState) , _log(Logger::getInstance("FLATBUFCONN")) , _registered(false) , _sent(false) , _lastSendImage(0) { - QStringList parts = address.split(":"); - if (parts.size() != 2) + if (_socket == nullptr) + Info(_log, "Connection using local domain socket. Ignoring port."); + else + Info(_log, "Connection using TCP socket (address != %s)", QSTRING_CSTR(HYPERHDR_DOMAIN_SERVER)); + + if (_socket != nullptr) { - throw std::runtime_error(QString("FLATBUFCONNECTION ERROR: Unable to parse address (%1)").arg(address).toStdString()); - } - _host = parts[0]; + QStringList parts = address.split(":"); + if (parts.size() != 2) + { + throw std::runtime_error(QString("FLATBUFCONNECTION ERROR: Unable to parse address (%1)").arg(address).toStdString()); + } + _host = parts[0]; - bool ok; - _port = parts[1].toUShort(&ok); - if (!ok) + bool ok; + _port = parts[1].toUShort(&ok); + if (!ok) + { + throw std::runtime_error(QString("FLATBUFCONNECTION ERROR: Unable to parse the port (%1)").arg(parts[1]).toStdString()); + } + } + else { - throw std::runtime_error(QString("FLATBUFCONNECTION ERROR: Unable to parse the port (%1)").arg(parts[1]).toStdString()); + _host = address; + _port = 0; } if (!skipReply) - connect(&_socket, &QTcpSocket::readyRead, this, &FlatBufferConnection::readData, Qt::UniqueConnection); + { + if (_socket != nullptr) + connect(_socket, &QTcpSocket::readyRead, this, &FlatBufferConnection::readData, Qt::UniqueConnection); + else if (_domain != nullptr) + connect(_domain, &QLocalSocket::readyRead, this, &FlatBufferConnection::readData, Qt::UniqueConnection); + } // init connect - Info(_log, "Connecting to HyperHDR: %s:%d", _host.toStdString().c_str(), _port); + if (_socket == nullptr) + Info(_log, "Connecting to HyperHDR local domain: %s", _host.toStdString().c_str()); + else + Info(_log, "Connecting to HyperHDR: %s:%d", _host.toStdString().c_str(), _port); + connectToHost(); // start the connection timer @@ -55,12 +79,19 @@ FlatBufferConnection::FlatBufferConnection(const QString& origin, const QString& FlatBufferConnection::~FlatBufferConnection() { _timer.stop(); - _socket.close(); + + if (_socket != nullptr) + _socket->close(); + if (_domain != nullptr) + _domain->close(); } void FlatBufferConnection::readData() { - _receiveBuffer += _socket.readAll(); + if (_socket != nullptr) + _receiveBuffer += _socket->readAll(); + else if (_domain != nullptr) + _receiveBuffer += _domain->readAll(); // check if we can read a header while (_receiveBuffer.size() >= 4) @@ -92,10 +123,20 @@ void FlatBufferConnection::readData() void FlatBufferConnection::setSkipReply(bool skip) { - if (skip) - disconnect(&_socket, &QTcpSocket::readyRead, 0, 0); - else - connect(&_socket, &QTcpSocket::readyRead, this, &FlatBufferConnection::readData, Qt::UniqueConnection); + if (_socket != nullptr) + { + if (skip) + disconnect(_socket, &QTcpSocket::readyRead, 0, 0); + else + connect(_socket, &QTcpSocket::readyRead, this, &FlatBufferConnection::readData, Qt::UniqueConnection); + } + if (_domain != nullptr) + { + if (skip) + disconnect(_domain, &QLocalSocket::readyRead, 0, 0); + else + connect(_domain, &QLocalSocket::readyRead, this, &FlatBufferConnection::readData, Qt::UniqueConnection); + } } void FlatBufferConnection::setRegister(const QString& origin, int priority) @@ -113,9 +154,19 @@ void FlatBufferConnection::setRegister(const QString& origin, int priority) // write message int count = 0; - count += _socket.write(reinterpret_cast(header), 4); - count += _socket.write(reinterpret_cast(_builder.GetBufferPointer()), size); - _socket.flush(); + + if (_socket != nullptr) + { + count += _socket->write(reinterpret_cast(header), 4); + count += _socket->write(reinterpret_cast(_builder.GetBufferPointer()), size); + _socket->flush(); + } + else if (_domain != nullptr) + { + count += _domain->write(reinterpret_cast(header), 4); + count += _domain->write(reinterpret_cast(_builder.GetBufferPointer()), size); + _domain->flush(); + } _builder.Clear(); } @@ -134,7 +185,10 @@ void FlatBufferConnection::setImage(const Image& image) auto current = QDateTime::currentMSecsSinceEpoch(); auto outOfTime = (current - _lastSendImage); - if (_socket.state() != QAbstractSocket::ConnectedState) + if (_socket != nullptr && _socket->state() != QAbstractSocket::ConnectedState) + return; + + if (_domain != nullptr && _domain->state() != QLocalSocket::ConnectedState) return; if (_sent && outOfTime < 1000) @@ -179,17 +233,19 @@ void FlatBufferConnection::clearAll() void FlatBufferConnection::connectToHost() { // try connection only when - if (_socket.state() == QAbstractSocket::UnconnectedState) - _socket.connectToHost(_host, _port); + if (_socket != nullptr && _socket->state() == QAbstractSocket::UnconnectedState) + _socket->connectToHost(_host, _port); + else if (_domain != nullptr && _domain->state() == QLocalSocket::UnconnectedState) + _domain->connectToServer(_host); } void FlatBufferConnection::sendMessage(const uint8_t* buffer, uint32_t size) { // print out connection message only when state is changed - if (_socket.state() != _prevSocketState) + if (_socket != nullptr && _socket->state() != _prevSocketState) { _registered = false; - switch (_socket.state()) + switch (_socket->state()) { case QAbstractSocket::UnconnectedState: Info(_log, "No connection to HyperHDR: %s:%d", _host.toStdString().c_str(), _port); @@ -201,11 +257,29 @@ void FlatBufferConnection::sendMessage(const uint8_t* buffer, uint32_t size) Debug(_log, "Connecting to HyperHDR: %s:%d", _host.toStdString().c_str(), _port); break; } - _prevSocketState = _socket.state(); + _prevSocketState = _socket->state(); } + if (_socket != nullptr && _socket->state() != QAbstractSocket::ConnectedState) + return; - - if (_socket.state() != QAbstractSocket::ConnectedState) + if (_domain != nullptr && _domain->state() != _prevLocalState) + { + _registered = false; + switch (_domain->state()) + { + case QLocalSocket::UnconnectedState: + Info(_log, "No connection to HyperHDR domain: %s", _host.toStdString().c_str()); + break; + case QLocalSocket::ConnectedState: + Info(_log, "Connected to HyperHDR domain: %s", _host.toStdString().c_str()); + break; + default: + Debug(_log, "Connecting to HyperHDR domain: %s", _host.toStdString().c_str()); + break; + } + _prevLocalState = _domain->state(); + } + if (_domain != nullptr && _domain->state() != QLocalSocket::ConnectedState) return; if (!_registered) @@ -222,9 +296,18 @@ void FlatBufferConnection::sendMessage(const uint8_t* buffer, uint32_t size) // write message int count = 0; - count += _socket.write(reinterpret_cast(header), 4); - count += _socket.write(reinterpret_cast(buffer), size); - _socket.flush(); + if (_socket != nullptr) + { + count += _socket->write(reinterpret_cast(header), 4); + count += _socket->write(reinterpret_cast(buffer), size); + _socket->flush(); + } + else if (_domain != nullptr) + { + count += _domain->write(reinterpret_cast(header), 4); + count += _domain->write(reinterpret_cast(buffer), size); + _domain->flush(); + } } bool FlatBufferConnection::parseReply(const hyperhdrnet::Reply* reply) diff --git a/sources/flatbufserver/FlatBufferServer.cpp b/sources/flatbufserver/FlatBufferServer.cpp index 758e9a93d..c9ad92b2a 100644 --- a/sources/flatbufserver/FlatBufferServer.cpp +++ b/sources/flatbufserver/FlatBufferServer.cpp @@ -14,6 +14,7 @@ // qt #include #include +#include #include #include #include @@ -26,6 +27,7 @@ FlatBufferServer* FlatBufferServer::instance = nullptr; FlatBufferServer::FlatBufferServer(const QJsonDocument& config, const QString& configurationPath, QObject* parent) : QObject(parent) , _server(new QTcpServer(this)) + , _domain(new QLocalServer(this)) , _log(Logger::getInstance("FLATBUFSERVER")) , _timeout(5000) , _config(config) @@ -40,7 +42,9 @@ FlatBufferServer::FlatBufferServer(const QJsonDocument& config, const QString& c FlatBufferServer::~FlatBufferServer() { stopServer(); + delete _server; + delete _domain; if (_lutBuffer != NULL) free(_lutBuffer); @@ -52,7 +56,11 @@ FlatBufferServer::~FlatBufferServer() void FlatBufferServer::initServer() { _netOrigin = NetOrigin::getInstance(); - connect(_server, &QTcpServer::newConnection, this, &FlatBufferServer::newConnection); + + if (_server != nullptr) + connect(_server, &QTcpServer::newConnection, this, &FlatBufferServer::newConnection); + if (_domain != nullptr) + connect(_domain, &QLocalServer::newConnection, this, &FlatBufferServer::newConnection); // apply config handleSettingsUpdate(settings::type::FLATBUFSERVER, _config); @@ -80,7 +88,7 @@ void FlatBufferServer::handleSettingsUpdate(settings::type type, const QJsonDocu quint16 port = obj["port"].toInt(19400); // port check - if (_server->serverPort() != port) + if (_server != nullptr && _server->serverPort() != port) { stopServer(); _port = port; @@ -98,30 +106,45 @@ void FlatBufferServer::handleSettingsUpdate(settings::type type, const QJsonDocu } } +void FlatBufferServer::setupClient(FlatBufferClient* client) +{ + connect(client, &FlatBufferClient::clientDisconnected, this, &FlatBufferServer::clientDisconnected); + connect(client, &FlatBufferClient::registerGlobalInput, GlobalSignals::getInstance(), &GlobalSignals::registerGlobalInput); + connect(client, &FlatBufferClient::clearGlobalInput, GlobalSignals::getInstance(), &GlobalSignals::clearGlobalInput); + connect(client, &FlatBufferClient::setGlobalInputImage, GlobalSignals::getInstance(), &GlobalSignals::setGlobalImage); + connect(client, &FlatBufferClient::setGlobalInputColor, GlobalSignals::getInstance(), &GlobalSignals::setGlobalColor); + connect(GlobalSignals::getInstance(), &GlobalSignals::globalRegRequired, client, &FlatBufferClient::registationRequired); + connect(this, &FlatBufferServer::hdrToneMappingChanged, client, &FlatBufferClient::setHdrToneMappingEnabled); + _openConnections.append(client); +} + void FlatBufferServer::newConnection() { - while (_server->hasPendingConnections()) + while (_server != nullptr && _server->hasPendingConnections()) { if (QTcpSocket* socket = _server->nextPendingConnection()) { if (_netOrigin->accessAllowed(socket->peerAddress(), socket->localAddress())) { Debug(_log, "New connection from %s", QSTRING_CSTR(socket->peerAddress().toString())); - FlatBufferClient* client = new FlatBufferClient(socket, _timeout, _hdrToneMappingMode, _lutBuffer, this); + FlatBufferClient* client = new FlatBufferClient(socket, nullptr, _timeout, _hdrToneMappingMode, _lutBuffer, this); // internal - connect(client, &FlatBufferClient::clientDisconnected, this, &FlatBufferServer::clientDisconnected); - connect(client, &FlatBufferClient::registerGlobalInput, GlobalSignals::getInstance(), &GlobalSignals::registerGlobalInput); - connect(client, &FlatBufferClient::clearGlobalInput, GlobalSignals::getInstance(), &GlobalSignals::clearGlobalInput); - connect(client, &FlatBufferClient::setGlobalInputImage, GlobalSignals::getInstance(), &GlobalSignals::setGlobalImage); - connect(client, &FlatBufferClient::setGlobalInputColor, GlobalSignals::getInstance(), &GlobalSignals::setGlobalColor); - connect(GlobalSignals::getInstance(), &GlobalSignals::globalRegRequired, client, &FlatBufferClient::registationRequired); - connect(this, &FlatBufferServer::hdrToneMappingChanged, client, &FlatBufferClient::setHdrToneMappingEnabled); - _openConnections.append(client); + setupClient(client); } else socket->close(); } } + while (_domain != nullptr && _domain->hasPendingConnections()) + { + if (QLocalSocket* socket = _domain->nextPendingConnection()) + { + Debug(_log, "New local domain connection"); + FlatBufferClient* client = new FlatBufferClient(nullptr, socket, _timeout, _hdrToneMappingMode, _lutBuffer, this); + // internal + setupClient(client); + } + } } void FlatBufferServer::clientDisconnected() @@ -133,7 +156,7 @@ void FlatBufferServer::clientDisconnected() void FlatBufferServer::startServer() { - if (!_server->isListening()) + if (_server != nullptr && !_server->isListening()) { if (!_server->listen(QHostAddress::Any, _port)) { @@ -157,18 +180,32 @@ void FlatBufferServer::startServer() #endif } } + if (_domain != nullptr && !_domain->isListening()) + { + if (!_domain->listen(HYPERHDR_DOMAIN_SERVER)) + Error(_log, "Could not start local domain server 'hyperhdr'"); + else + Info(_log, "Started local domain server: %s", QSTRING_CSTR(_domain->serverName())); + } } void FlatBufferServer::stopServer() { - if (_server->isListening()) + if ((_server != nullptr &&_server->isListening()) || (_domain != nullptr && _domain->isListening())) { // close client connections for (const auto& client : _openConnections) { client->forceClose(); } - _server->close(); + + // closing + if (_server != nullptr) + _server->close(); + + if (_domain != nullptr) + _domain->close(); + Info(_log, "Stopped"); } }