C
Message Proxy: Testing Qt Safe Renderer Messaging Interface
// Copyright (C) 2021 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial // This file is part of the Qt Safe Renderer module #include <QtNetwork/QTcpSocket> #include <QtSafeRenderer/qsafeevent.h> #include "server.h" namespace { constexpr int MaxReadBufferSize = 1024; } // anonymous namespace Server::Server(const quint16 port, QObject *parent) : QObject(parent) { runServer(port); } void Server::runServer(const quint16 port) { m_tcpServer = new QTcpServer(this); if (!m_tcpServer->listen(QHostAddress::Any, port)) { qCritical() << "Unable to start the server: " << m_tcpServer->errorString(); return; } connect(m_tcpServer, &QTcpServer::newConnection, this, &Server::newConnection); QString ipAddress; QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses(); // use the first non-localhost IPv4 address for (int i = 0U; i < ipAddressesList.size(); ++i) { if (ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address()) { ipAddress = ipAddressesList.at(i).toString(); break; } } // if we did not find one, use IPv4 localhost if (ipAddress.isEmpty()) ipAddress = QHostAddress(QHostAddress::LocalHost).toString(); qDebug() << "The server is running on: " << ipAddress << ":" << m_tcpServer->serverPort(); } void Server::newConnection() { QTcpSocket *clientConnection = m_tcpServer->nextPendingConnection(); connect(clientConnection, &QAbstractSocket::disconnected, clientConnection, &QObject::deleteLater); connect(clientConnection, &QAbstractSocket::readyRead, this, &Server::readData); } static bool sendReply(QTcpSocket &clientConnection, const SafeRenderer::QSafeEvent &reply) { bool success = false; const quint64 bytesWritten = clientConnection.write(reinterpret_cast<const char*>(reply.rawData().data()), SafeRenderer::SafeMessageLength); if (bytesWritten == SafeRenderer::SafeMessageLength) { success = true; } else { qDebug() << "Failed to send reply to client"; } return success; } void Server::readData() { QTcpSocket *clientConnection = qobject_cast<QTcpSocket *>(QObject::sender()); if (clientConnection) { SafeRenderer::QSafeEvent::SafeMessageData dataBuffer; char readBuffer[MaxReadBufferSize]; quint32 writePointer = 0; int bytesRead = 0; do { bytesRead = clientConnection->read(&readBuffer[writePointer], MaxReadBufferSize - writePointer); if (bytesRead == 0) { // No more data } else if (bytesRead == -1) { // Socket closed / disconnected / read error } else { writePointer += bytesRead; } } while (bytesRead > 0); // Now handle all the packets received QByteArray data(readBuffer, writePointer); quint32 dataLeft = writePointer; quint32 readPointer = 0; do { if (dataLeft >= SafeRenderer::SafeMessageLength) { std::copy(data.data() + readPointer, data.data() + readPointer + SafeRenderer::SafeMessageLength, dataBuffer.begin()); readPointer += SafeRenderer::SafeMessageLength; SafeRenderer::QSafeEvent safeEvent(dataBuffer); SafeRenderer::QSafeEvent reply; SafeRenderer::SafeEventSenderStatus status = m_messageSender.sendEvent(safeEvent, reply); if (status == SafeRenderer::SafeEventSenderStatus::Success) { sendReply(*clientConnection, reply); } else { qDebug() << "Failed to send request to renderer."; } dataLeft -= SafeRenderer::SafeMessageLength; } else { // Partial packet, we can do nothing but discard it. dataLeft = 0; } } while (dataLeft > 0); } }