From 64de9e9b0856afed336700bcb2e70b6939040c8d Mon Sep 17 00:00:00 2001 From: MattKC <34096995+itsmattkc@users.noreply.github.com> Date: Sun, 4 Aug 2024 14:36:55 -0700 Subject: [PATCH] rework UDP backend for more event based system --- app/backend.cpp | 242 +++++++++++---------------------------------- app/backend.h | 80 +++------------ app/mainwindow.cpp | 5 +- pipe/pipe.h | 2 +- 4 files changed, 81 insertions(+), 248 deletions(-) diff --git a/app/backend.cpp b/app/backend.cpp index bdc1d0a..8a08969 100644 --- a/app/backend.cpp +++ b/app/backend.cpp @@ -1,5 +1,6 @@ #include "backend.h" +#include #include #include #include @@ -49,48 +50,39 @@ BackendViaPipe::BackendViaPipe(QObject *parent) : Backend(parent) { } -BackendViaNamedPipe::BackendViaNamedPipe(const QString &wirelessInterface, QObject *parent) : BackendViaPipe(parent) -{ - m_pipeIn = -1; - m_pipeOut = -1; - m_pipeThread = new QThread(this); - m_pipe = new BackendPipe(wirelessInterface, this); - connect(m_pipe, &BackendPipe::pipesAvailable, this, &BackendViaNamedPipe::setUpPipes); - connect(m_pipe, &BackendPipe::closed, this, &BackendViaNamedPipe::closed); -} - -void BackendViaNamedPipe::init() -{ - m_pipe->setParent(nullptr); - m_pipeThread->start(); - m_pipe->moveToThread(m_pipeThread); - QMetaObject::invokeMethod(m_pipe, &BackendPipe::start, Qt::QueuedConnection); -} - BackendViaSocket::BackendViaSocket(const QHostAddress &backendAddr, quint16 backendPort, QObject *parent) : BackendViaPipe(parent) { - m_socket = new BackendUdpWrapper(backendAddr, backendPort, this); - connect(m_socket, &BackendUdpWrapper::socketReady, this, &BackendViaSocket::socketReady); - connect(m_socket, &BackendUdpWrapper::receivedData, this, &BackendViaSocket::receivedData, Qt::DirectConnection); - connect(m_socket, &BackendUdpWrapper::closed, this, &BackendViaSocket::closed); - connect(m_socket, &BackendUdpWrapper::error, this, &BackendViaSocket::error); + m_backendAddress = backendAddr; + m_backendPort = backendPort; - m_socketThread = new QThread(this); -} - -BackendViaSocket::~BackendViaSocket() -{ - m_socket->deleteLater(); - m_socketThread->quit(); - m_socketThread->wait(); + m_socket = new QUdpSocket(this); + connect(m_socket, &QUdpSocket::readyRead, this, &BackendViaSocket::readPendingDatagrams); + connect(m_socket, &QUdpSocket::disconnected, this, &BackendViaSocket::closed); } void BackendViaSocket::init() { - m_socketThread->start(); - m_socket->setParent(nullptr); - m_socket->moveToThread(m_socketThread); - QMetaObject::invokeMethod(m_socket, &BackendUdpWrapper::start, Qt::QueuedConnection); + bool connected = false; + + for (m_frontendPort = 10100; m_frontendPort < 10200; m_frontendPort++) { + printf("Trying to bind to port %u\n", m_frontendPort); + if (m_socket->bind(QHostAddress::Any, m_frontendPort)) { + printf("Bound to port %u\n", m_frontendPort); + connected = true; + break; + } + } + + if (connected) { + // Send bind command to backend + pipe_control_code cmd; + cmd.code = VANILLA_PIPE_IN_BIND; + writeToPipe(&cmd, sizeof(cmd)); + } else { + printf("Failed to bind to port\n"); + emit error(tr("Failed to bind to UDP port")); + emit closed(); + } } void BackendViaPipe::quitPipe() @@ -100,15 +92,6 @@ void BackendViaPipe::quitPipe() writeToPipe(&cmd, sizeof(cmd)); } -BackendViaNamedPipe::~BackendViaNamedPipe() -{ - quitPipe(); - - m_pipe->deleteLater(); - m_pipeThread->quit(); - m_pipeThread->wait(); -} - void BackendViaLocalRoot::interrupt() { vanilla_stop(); @@ -144,30 +127,42 @@ int BackendViaLocalRoot::connectInternal(BackendViaLocalRoot *instance, const QS return vanilla_connect_to_console(wirelessInterfaceC.constData(), vanillaEventHandler, instance); } +void BackendViaPipe::processPacket(const QByteArray &arr) +{ + const pipe_control_code *cc = (const pipe_control_code *) arr.data(); + + switch (cc->code) { + case VANILLA_PIPE_OUT_EOF: + // Do nothing? + break; + case VANILLA_PIPE_OUT_DATA: + { + pipe_data_command *event = (pipe_data_command *) cc; + event->data_size = ntohs(event->data_size); + vanillaEventHandler(this, event->event_type, (const char *) event->data, event->data_size); + break; + } + case VANILLA_PIPE_OUT_BOUND_SUCCESSFUL: + emit ready(); + break; + case VANILLA_PIPE_ERR_SUCCESS: + printf("ERR_SUCCESS code\n"); + break; + case VANILLA_PIPE_OUT_SYNC_STATE: + { + const pipe_sync_state_command *ss = (const pipe_sync_state_command *) cc; + emit syncCompleted(ss->state == VANILLA_SUCCESS); + break; + } + } +} + void BackendViaPipe::connectToConsole() { // Request pipe to connect pipe_control_code conn_cmd; conn_cmd.code = VANILLA_PIPE_IN_CONNECT; writeToPipe(&conn_cmd, sizeof(conn_cmd)); - - uint8_t cmd[UINT16_MAX]; - while (true) { - ssize_t read_size = readFromPipe(cmd, sizeof(cmd)); - if (read_size == 0) { - continue; - } - - pipe_control_code *cc = (pipe_control_code *) cmd; - - if (cc->code == VANILLA_PIPE_OUT_EOF) { - break; - } else if (cc->code == VANILLA_PIPE_OUT_DATA) { - pipe_data_command *event = (pipe_data_command *) cmd; - event->data_size = ntohs(event->data_size); - vanillaEventHandler(this, event->event_type, (const char *) event->data, event->data_size); - } - } } void BackendViaLocalRoot::updateTouch(int x, int y) @@ -252,40 +247,6 @@ void BackendViaPipe::sync(uint16_t code) cmd.base.code = VANILLA_PIPE_IN_SYNC; cmd.code = htons(code); writeToPipe(&cmd, sizeof(cmd)); - - // See if pipe accepted our request to sync - uint8_t cc; - readFromPipe(&cc, sizeof(cc)); - if (cc != VANILLA_PIPE_ERR_SUCCESS) { - emit syncCompleted(false); - return; - } - - // Wait for sync status - readFromPipe(&cc, sizeof(cc)); - if (cc == VANILLA_PIPE_OUT_SYNC_STATE) { - readFromPipe(&cc, sizeof(cc)); - emit syncCompleted(cc == VANILLA_SUCCESS); - } else { - emit syncCompleted(false); - } -} - -void BackendViaNamedPipe::setUpPipes(const QString &in, const QString &out) -{ - QByteArray inUtf8 = in.toUtf8(); - QByteArray outUtf8 = out.toUtf8(); - m_pipeIn = open(inUtf8.constData(), O_RDONLY); - if (m_pipeIn == -1) { - QMessageBox::critical(nullptr, tr("Pipe Error"), tr("Failed to create in pipe: %1").arg(strerror(errno))); - } - m_pipeOut = open(outUtf8.constData(), O_WRONLY); - if (m_pipeOut == -1) { - QMessageBox::critical(nullptr, tr("Pipe Error"), tr("Failed to create out pipe: %1").arg(strerror(errno))); - } - - printf("Established connection with backend\n"); - emit ready(); } BackendPipe::BackendPipe(const QString &wirelessInterface, QObject *parent) : QObject(parent) @@ -335,98 +296,15 @@ void BackendPipe::receivedData() } } -ssize_t BackendViaNamedPipe::readFromPipe(void *data, size_t length) -{ - return read(m_pipeIn, data, length); -} - -ssize_t BackendViaNamedPipe::writeToPipe(const void *data, size_t length) -{ - return write(m_pipeOut, data, length); -} - -BackendUdpWrapper::BackendUdpWrapper(const QHostAddress &backendAddr, quint16 backendPort, QObject *parent) : QObject(parent) -{ - m_backendAddress = backendAddr; - m_backendPort = backendPort; - - m_socket = new QUdpSocket(this); - connect(m_socket, &QUdpSocket::readyRead, this, &BackendUdpWrapper::readPendingDatagrams); -} - -void BackendUdpWrapper::start() -{ - bool connected = false; - - for (m_frontendPort = 10100; m_frontendPort < 10200; m_frontendPort++) { - printf("Trying to bind to port %u\n", m_frontendPort); - if (m_socket->bind(QHostAddress::Any, m_frontendPort)) { - printf("Bound to port %u\n", m_frontendPort); - connected = true; - break; - } - } - - if (connected) { - emit socketReady(m_frontendPort); - } else { - printf("Failed to bind to port\n"); - emit error(tr("Failed to bind to UDP port")); - emit closed(); - } -} - -void BackendUdpWrapper::readPendingDatagrams() +void BackendViaSocket::readPendingDatagrams() { while (m_socket->hasPendingDatagrams()) { QNetworkDatagram datagram = m_socket->receiveDatagram(); - emit receivedData(datagram.data()); + processPacket(datagram.data()); } } -void BackendUdpWrapper::write(const QByteArray &data) -{ - m_socket->writeDatagram(data, m_backendAddress, m_backendPort); -} - -ssize_t BackendViaSocket::readFromPipe(void *data, size_t length) -{ - m_readMutex.lock(); - if (m_buffer.isEmpty()) { - m_readWaitCond.wait(&m_readMutex); - } - if (m_buffer.size() < length) { - length = m_buffer.size(); - } - memcpy(data, m_buffer.constData(), length); - m_buffer.remove(0, length); - m_readMutex.unlock(); - return length; -} - ssize_t BackendViaSocket::writeToPipe(const void *data, size_t length) { - QMetaObject::invokeMethod(m_socket, "write", Q_ARG(QByteArray, QByteArray((const char *) data, length))); - return length; -} - -void BackendViaSocket::receivedData(const QByteArray &data) -{ - m_readMutex.lock(); - m_buffer.append(data); - m_readWaitCond.wakeAll(); - m_readMutex.unlock(); -} - -void BackendViaSocket::socketReady(quint16 port) -{ - pipe_control_code cmd; - cmd.code = VANILLA_PIPE_IN_BIND; - writeToPipe(&cmd, sizeof(cmd)); - - uint8_t cc; - readFromPipe(&cc, sizeof(cc)); - if (cc == VANILLA_PIPE_OUT_BOUND_SUCCESSFUL) { - emit ready(); - } + return m_socket->writeDatagram((const char *) data, length, m_backendAddress, m_backendPort); } \ No newline at end of file diff --git a/app/backend.h b/app/backend.h index 6562811..c0a25bb 100644 --- a/app/backend.h +++ b/app/backend.h @@ -103,6 +103,13 @@ class BackendViaPipe : public Backend { Q_OBJECT public: + enum ListenState { + IDLE, + WAITING_FOR_SYNC_RESULT, + WAITING_FOR_BIND_RESULT, + RECEIVING_DATA + }; + BackendViaPipe(QObject *parent = nullptr); virtual void interrupt() override; @@ -116,55 +123,29 @@ public slots: virtual void sync(uint16_t code) override; virtual void connectToConsole() override; -protected slots: - virtual ssize_t readFromPipe(void *data, size_t length) = 0; + void quitPipe(); + +protected: + void processPacket(const QByteArray &arr); virtual ssize_t writeToPipe(const void *data, size_t length) = 0; - void quitPipe(); +private: + ListenState m_listenState; }; -class BackendViaNamedPipe : public BackendViaPipe +class BackendViaSocket : public BackendViaPipe { Q_OBJECT public: - BackendViaNamedPipe(const QString &wirelessInterface, QObject *parent = nullptr); - virtual ~BackendViaNamedPipe() override; + BackendViaSocket(const QHostAddress &backendAddr, quint16 backendPort, QObject *parent = nullptr); public slots: virtual void init() override; -private: - BackendPipe *m_pipe; - QThread *m_pipeThread; - int m_pipeIn; - int m_pipeOut; - -protected slots: - virtual ssize_t readFromPipe(void *data, size_t length) override; +protected: virtual ssize_t writeToPipe(const void *data, size_t length) override; -private slots: - void setUpPipes(const QString &in, const QString &out); - -}; - -class BackendUdpWrapper : public QObject -{ - Q_OBJECT -public: - BackendUdpWrapper(const QHostAddress &backendAddr, quint16 backendPort, QObject *parent = nullptr); - -public slots: - void start(); - void write(const QByteArray &data); - -signals: - void receivedData(const QByteArray &data); - void socketReady(quint16 port); - void closed(); - void error(const QString &err); - private: QUdpSocket *m_socket; QHostAddress m_backendAddress; @@ -176,33 +157,4 @@ private slots: }; -class BackendViaSocket : public BackendViaPipe -{ - Q_OBJECT -public: - BackendViaSocket(const QHostAddress &backendAddr, quint16 backendPort, QObject *parent = nullptr); - virtual ~BackendViaSocket() override; - -public slots: - virtual void init() override; - -protected slots: - virtual ssize_t readFromPipe(void *data, size_t length) override; - virtual ssize_t writeToPipe(const void *data, size_t length) override; - -private: - BackendUdpWrapper *m_socket; - QThread *m_socketThread; - - QByteArray m_buffer; - - QMutex m_readMutex; - QWaitCondition m_readWaitCond; - -private slots: - void receivedData(const QByteArray &data); - void socketReady(quint16 port); - -}; - #endif // BACKEND_H \ No newline at end of file diff --git a/app/mainwindow.cpp b/app/mainwindow.cpp index cb09b50..9153c70 100644 --- a/app/mainwindow.cpp +++ b/app/mainwindow.cpp @@ -358,7 +358,10 @@ void MainWindow::initBackend(T func) } } else if ((geteuid() != 0)) { // If not root, use named pipe - m_backend = new BackendViaNamedPipe(localWirelessIntf); + QMessageBox::critical(this, QString(), tr("Unimplemented...")); + d->deleteLater(); + return; + //m_backend = new BackendViaNamedPipe(localWirelessIntf); } else { // If root, use lib locally m_backend = new BackendViaLocalRoot(localWirelessIntf); diff --git a/pipe/pipe.h b/pipe/pipe.h index d860716..4dfbfc1 100644 --- a/pipe/pipe.h +++ b/pipe/pipe.h @@ -78,7 +78,7 @@ struct pipe_data_command struct pipe_control_code base; uint8_t event_type; uint16_t data_size; - uint8_t data[UINT16_MAX]; + uint8_t data[2048]; }; #pragma pack(pop)