From 128423cb295e9ee48b10ce2dd7cf58c2eebca1b3 Mon Sep 17 00:00:00 2001 From: Carlo Castoldi Date: Tue, 15 Nov 2022 12:23:47 +0100 Subject: [PATCH] REFAC(ipc): extract IPCUtils for Socket and OverlayPipe --- overlay/CMakeLists.txt | 2 + overlay/ipc_utils.c | 101 ++++++++++++++++++++++++++ overlay/ipc_utils.h | 13 ++++ overlay_gl/overlay.c | 37 ++-------- src/mumble/CMakeLists.txt | 4 + src/mumble/IPCUtils.cpp | 49 +++++++++++++ src/mumble/IPCUtils.h | 30 ++++++++ src/mumble/Overlay.cpp | 28 ++----- src/mumble/SocketRPC.cpp | 50 +++---------- src/tests/OverlayTest/OverlayTest.cpp | 31 ++++---- 10 files changed, 234 insertions(+), 111 deletions(-) create mode 100644 overlay/ipc_utils.c create mode 100644 overlay/ipc_utils.h create mode 100644 src/mumble/IPCUtils.cpp create mode 100644 src/mumble/IPCUtils.h diff --git a/overlay/CMakeLists.txt b/overlay/CMakeLists.txt index 62b2ab1ba99..5d2c8d07e59 100644 --- a/overlay/CMakeLists.txt +++ b/overlay/CMakeLists.txt @@ -94,6 +94,8 @@ target_sources(overlay "dxgi.cpp" "excludecheck.cpp" "excludecheck.h" + "ipc_utils.h" + "ipc_utils.c" "lib.cpp" "lib.h" "ods.cpp" diff --git a/overlay/ipc_utils.c b/overlay/ipc_utils.c new file mode 100644 index 00000000000..1286320a64d --- /dev/null +++ b/overlay/ipc_utils.c @@ -0,0 +1,101 @@ +// Copyright 2007-2022 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +#include "ipc_utils.h" +#include + +#ifdef __unix__ +# include +# include +# include +# include +# include +# include +#else +# include +#endif + +char *getRuntimePath__() { + size_t n = 0; + char *path = NULL; + +#ifdef __linux__ + char *xdgRuntimeDir = getenv("XDG_RUNTIME_DIR"); + + if (xdgRuntimeDir != NULL) { + if (xdgRuntimeDir) + n += strlen(xdgRuntimeDir); + if (xdgRuntimeDir[(strlen(xdgRuntimeDir) - 1)] != '/') + n++; + n += strlen("mumble/"); + + if ((path = malloc(n + 1)) == NULL) + return path; + *path = '\0'; + + strcpy(path, xdgRuntimeDir); + if (xdgRuntimeDir[(strlen(xdgRuntimeDir) - 1)] != '/') + strcat(path, "/"); + strcat(path, "mumble/"); + } else { + char uid[10]; + n += strlen("/run/user//mumble/"); + sprintf(uid, "%d", getuid()); + n += strlen(uid); + + if ((path = malloc(n + 1)) == NULL) + return path; + *path = '\0'; + + strcpy(path, "/run/user/"); + strcat(path, uid); + strcat(path, "/mumble/"); + } +#elif defined __unix__ + char *home = getenv("HOME"); + if (home == NULL) { + struct passwd *pwent = getpwuid(getuid()); + if (pwent && pwent->pw_dir && pwent->pw_dir[0]) + home = pwent->pw_dir; + } + if (home == NULL) + return NULL; + n += strlen(home); + if (home[(strlen(home) - 1)] != '/') + n++; + if ((path = malloc(n + 1)) == NULL) + return path; + strcpy(path, home); + if (home[(strlen(home) - 1)] != '/') + strcat(path, "/"); +#else + path = strdup(""); +#endif + return path; +} + +char *getAndCreateOverlayPipePath__() { + char *runtimePath = getRuntimePath__(); + char *path = NULL; + if (runtimePath == NULL) + return runtimePath; +#ifdef __unix__ + mkdir(runtimePath, 0755); +#else + _mkdir(runtimePath); +#endif + size_t n = 1; + n += strlen(runtimePath); + n += strlen("MumbleOverlayPipe"); + if ((path = malloc(n + 1)) == NULL) + return path; +#if !defined __linux__ && !defined _WIN32 + strcat(path, "."); +#endif + strcpy(path, runtimePath); + strcat(path, "MumbleOverlayPipe"); + free(runtimePath); + return path; +} \ No newline at end of file diff --git a/overlay/ipc_utils.h b/overlay/ipc_utils.h new file mode 100644 index 00000000000..9bd90975cd1 --- /dev/null +++ b/overlay/ipc_utils.h @@ -0,0 +1,13 @@ +// Copyright 2015-2022 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +#ifndef MUMBLE_OVERLAY_IPC_UTILS_H__ +#define MUMBLE_OVERLAY_IPC_UTILS_H__ + +char *getRuntimePath__(); + +char *getAndCreateOverlayPipePath__(); + +#endif // MUMBLE_OVERLAY_IPC_UTILS_H__ \ No newline at end of file diff --git a/overlay_gl/overlay.c b/overlay_gl/overlay.c index 8ea1de7ac92..fcbababf00d 100644 --- a/overlay_gl/overlay.c +++ b/overlay_gl/overlay.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -53,6 +52,7 @@ typedef unsigned char bool; # include "avail_mac.h" #endif +#include "../overlay/ipc_utils.h" #include "../overlay/overlay.h" static bool bDebug = false; @@ -147,37 +147,10 @@ static void newContext(Context *ctx) { ctx->timeT = clock(); ctx->frameCount = 0; -#ifdef __linux__ - char *xdgRuntimeDir = getenv("XDG_RUNTIME_DIR"); - - if (xdgRuntimeDir != NULL) { - ctx->saName.sun_family = PF_UNIX; - strcpy(ctx->saName.sun_path, xdgRuntimeDir); - if(xdgRuntimeDir[(strlen(xdgRuntimeDir)-1)] != '/') - strcat(ctx->saName.sun_path, "/"); - strcat(ctx->saName.sun_path, "mumble/MumbleOverlayPipe"); - } else { - char uid[10]; - sprintf(uid, "%d", getuid()); - ctx->saName.sun_family = PF_UNIX; - strcpy(ctx->saName.sun_path, "/run/user/"); - strcat(ctx->saName.sun_path, uid); - strcat(ctx->saName.sun_path, "/mumble/MumbleOverlayPipe"); - } -#else - char *home = getenv("HOME"); - if (home == NULL) { - struct passwd *pwent = getpwuid(getuid()); - if (pwent && pwent->pw_dir && pwent->pw_dir[0]) { - home = pwent->pw_dir; - } - } - if (home) { - ctx->saName.sun_family = PF_UNIX; - strcpy(ctx->saName.sun_path, home); - strcat(ctx->saName.sun_path, "/MumbleOverlayPipe"); - } -#endif + char *path = getAndCreateOverlayPipePath__(); + strcpy(ctx->saName.sun_path, path); + free(path); + ctx->saName.sun_family = PF_UNIX; ods("OpenGL Version %s, Vendor %s, Renderer %s, Shader %s", glGetString(GL_VERSION), glGetString(GL_VENDOR), glGetString(GL_RENDERER), glGetString(GL_SHADING_LANGUAGE_VERSION)); diff --git a/src/mumble/CMakeLists.txt b/src/mumble/CMakeLists.txt index 425ba596c51..9f05d27a160 100644 --- a/src/mumble/CMakeLists.txt +++ b/src/mumble/CMakeLists.txt @@ -156,6 +156,10 @@ set(MUMBLE_SOURCES "GlobalShortcutButtons.ui" "GlobalShortcutTarget.ui" "GlobalShortcutTypes.h" + "IPCUtils.cpp" + "IPCUtils.h" + "${CMAKE_SOURCE_DIR}/overlay/ipc_utils.c" + "${CMAKE_SOURCE_DIR}/overlay/ipc_utils.h" "JSONSerialization.cpp" "JSONSerialization.h" "LCD.cpp" diff --git a/src/mumble/IPCUtils.cpp b/src/mumble/IPCUtils.cpp new file mode 100644 index 00000000000..16932d40415 --- /dev/null +++ b/src/mumble/IPCUtils.cpp @@ -0,0 +1,49 @@ +// Copyright 2021-2022 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +#include "IPCUtils.h" +extern "C" { + #include "../../overlay/ipc_utils.h" +} + +#include +#include +#include + +namespace Mumble { + const std::string getRuntimePath(void) { + char* c_mumbleRuntimePath = getRuntimePath__(); + if (c_mumbleRuntimePath == NULL) + return ""; + std::string mumbleRuntimePath = c_mumbleRuntimePath; + return mumbleRuntimePath; + } + + const std::string getAndCreateOverlayPipePath(void) { + char* c_pipepath = getAndCreateOverlayPipePath__(); + if (c_pipepath == NULL) + return ""; + std::string pipepath = c_pipepath; + return pipepath; + } + + const std::string getAndCreateSocketPath(const std::string &basename) { + const std::string mumbleRuntimePath = getRuntimePath(); +#ifdef Q_OS_WIN + return basename; +#endif + if (mumbleRuntimePath.empty()) + return ""; + QString qMumbleRuntimePath = QString::fromUtf8(mumbleRuntimePath.data(), int(mumbleRuntimePath.size())); + QDir(qMumbleRuntimePath).mkpath("."); +#ifdef Q_OS_LINUX + std::string pipepath = mumbleRuntimePath + basename + "Socket"; +#else // MAC or BSD + const std::string pipepath = mumbleRuntimePath + "." + basename + "Socket"; +#endif + return pipepath; + } + +}; // namespace Mumble diff --git a/src/mumble/IPCUtils.h b/src/mumble/IPCUtils.h new file mode 100644 index 00000000000..05df18ea735 --- /dev/null +++ b/src/mumble/IPCUtils.h @@ -0,0 +1,30 @@ +// Copyright 2021-2022 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +#ifndef MUMBLE_MUMBLE_IPCUTILS_H_ +#define MUMBLE_MUMBLE_IPCUTILS_H_ + +#include + +namespace Mumble { + + /** + * @returns The path to MumbleOverlayPipe + */ + const std::string getAndCreateOverlayPipePath(); + + /** + * @returns The path to MumbleSocket + */ + const std::string getAndCreateSocketPath(const std::string &); + + /** + * @returns The path where Mumble sets up MumbleOverlayPipe and MumbleSocket + */ + const std::string getRuntimePath(); + +}; // namespace Mumble + +#endif // MUMBLE_MUMBLE_IPCUTILS_H_ diff --git a/src/mumble/Overlay.cpp b/src/mumble/Overlay.cpp index ed8c5f5d026..84be1eb8fab 100644 --- a/src/mumble/Overlay.cpp +++ b/src/mumble/Overlay.cpp @@ -8,6 +8,7 @@ #include "Channel.h" #include "ClientUser.h" #include "Database.h" +#include "IPCUtils.h" #include "MainWindow.h" #include "OverlayClient.h" #include "OverlayText.h" @@ -238,36 +239,21 @@ void Overlay::createPipe() { // Allow anyone to access the pipe in order to communicate with the overlay qlsServer->setSocketOptions(QLocalServer::WorldAccessOption); - QString pipepath; -#ifdef Q_OS_WIN - pipepath = QLatin1String("MumbleOverlayPipe"); -#else - { - QString xdgRuntimePath = QProcessEnvironment::systemEnvironment().value(QLatin1String("XDG_RUNTIME_DIR")); - QString mumbleRuntimePath; - if (!xdgRuntimePath.isNull()) { - mumbleRuntimePath = QDir(xdgRuntimePath).absolutePath() + QLatin1String("/mumble/"); - } else { - mumbleRuntimePath = QLatin1String("/run/user/") + QString::number(getuid()) + QLatin1String("/mumble/"); - } - QDir mumbleRuntimeDir = QDir(mumbleRuntimePath); - mumbleRuntimeDir.mkpath("."); - pipepath = mumbleRuntimeDir.absoluteFilePath(QLatin1String("MumbleOverlayPipe")); - } + const std::string pipepath = Mumble::getAndCreateOverlayPipePath(); + QString qPipepath = QString::fromUtf8(pipepath.data(), int(pipepath.size())); { - QFile f(pipepath); + QFile f(qPipepath); if (f.exists()) { - qWarning() << "Overlay: Removing old socket on" << pipepath; + qWarning() << "Overlay: Removing old socket on" << qPipepath; f.remove(); } } -#endif - if (!qlsServer->listen(pipepath)) { + if (!qlsServer->listen(qPipepath)) { QMessageBox::warning(nullptr, QLatin1String("Mumble"), tr("Failed to create communication with overlay at %2: %1. No overlay will be available.") - .arg(qlsServer->errorString().toHtmlEscaped(), pipepath.toHtmlEscaped()), + .arg(qlsServer->errorString().toHtmlEscaped(), qPipepath.toHtmlEscaped()), QMessageBox::Ok, QMessageBox::NoButton); } else { qWarning() << "Overlay: Listening on" << qlsServer->fullServerName(); diff --git a/src/mumble/SocketRPC.cpp b/src/mumble/SocketRPC.cpp index bf1bcb6c6ad..eb0e181ee72 100644 --- a/src/mumble/SocketRPC.cpp +++ b/src/mumble/SocketRPC.cpp @@ -7,6 +7,7 @@ #include "Channel.h" #include "ClientUser.h" +#include "IPCUtils.h" #include "MainWindow.h" #include "ServerHandler.h" #include "Global.h" @@ -229,34 +230,18 @@ void SocketRPCClient::processXml() { SocketRPC::SocketRPC(const QString &basename, QObject *p) : QObject(p) { qlsServer = new QLocalServer(this); - QString pipepath; + const std::string pipepath = Mumble::getAndCreateSocketPath(basename.toStdString()); + QString qPipepath = QString::fromUtf8(pipepath.data(), int(pipepath.size())); -#ifdef Q_OS_WIN - pipepath = basename; -#else { - QString xdgRuntimePath = QProcessEnvironment::systemEnvironment().value(QLatin1String("XDG_RUNTIME_DIR")); - QString mumbleRuntimePath; - if (!xdgRuntimePath.isNull()) { - mumbleRuntimePath = QDir(xdgRuntimePath).absolutePath() + QLatin1String("/mumble/"); - } else { - mumbleRuntimePath = QLatin1String("/run/user/") + QString::number(getuid()) + QLatin1String("/mumble/"); - } - QDir mumbleRuntimeDir = QDir(mumbleRuntimePath); - mumbleRuntimeDir.mkpath("."); - pipepath = mumbleRuntimeDir.absoluteFilePath(basename + QLatin1String("Socket")); - } - - { - QFile f(pipepath); + QFile f(qPipepath); if (f.exists()) { - qWarning() << "SocketRPC: Removing old socket on" << pipepath; + qWarning() << "SocketRPC: Removing old socket on" << qPipepath; f.remove(); } } -#endif - if (!qlsServer->listen(pipepath)) { + if (!qlsServer->listen(qPipepath)) { qWarning() << "SocketRPC: Listen failed"; delete qlsServer; qlsServer = nullptr; @@ -275,27 +260,11 @@ void SocketRPC::newConnection() { } bool SocketRPC::send(const QString &basename, const QString &request, const QMap< QString, QVariant > ¶m) { - QString pipepath; - -#ifdef Q_OS_WIN - pipepath = basename; -#else - { - QString xdgRuntimePath = QProcessEnvironment::systemEnvironment().value(QLatin1String("XDG_RUNTIME_DIR")); - QString mumbleRuntimePath; - if (!xdgRuntimePath.isNull()) { - mumbleRuntimePath = QDir(xdgRuntimePath).absolutePath() + QLatin1String("/mumble/"); - } else { - mumbleRuntimePath = QLatin1String("/run/user/") + QString::number(getuid()) + QLatin1String("/mumble/"); - } - QDir mumbleRuntimeDir = QDir(mumbleRuntimePath); - mumbleRuntimeDir.mkpath("."); - pipepath = mumbleRuntimeDir.absoluteFilePath(basename + QLatin1String("Socket")); - } -#endif + const std::string pipepath = Mumble::getAndCreateSocketPath(basename.toStdString()); + QString qPipepath = QString::fromUtf8(pipepath.data(), int(pipepath.size())); QLocalSocket qls; - qls.connectToServer(pipepath); + qls.connectToServer(qPipepath); if (!qls.waitForConnected(1000)) { return false; } @@ -329,4 +298,3 @@ bool SocketRPC::send(const QString &basename, const QString &request, const QMap return QVariant(succ.text()).toBool(); } - diff --git a/src/tests/OverlayTest/OverlayTest.cpp b/src/tests/OverlayTest/OverlayTest.cpp index 573c05a63a4..cf0c215eb6e 100644 --- a/src/tests/OverlayTest/OverlayTest.cpp +++ b/src/tests/OverlayTest/OverlayTest.cpp @@ -8,6 +8,9 @@ */ #include "../../overlay/overlay.h" +extern "C" { + #include "../../overlay/ipc_utils.h" +} #include "SharedMemory.h" #include "Timer.h" @@ -15,7 +18,7 @@ #ifdef Q_OS_WIN # include "win.h" #else -# include +# include #endif #include @@ -26,7 +29,6 @@ #include #include - class OverlayWidget : public QWidget { Q_OBJECT @@ -98,22 +100,17 @@ void OverlayWidget::paintEvent(QPaintEvent *) { connect(qlsSocket, SIGNAL(readyRead()), this, SLOT(readyRead())); connect(qlsSocket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(error(QLocalSocket::LocalSocketError))); -#ifdef Q_OS_WIN - qlsSocket->connectToServer(QLatin1String("MumbleOverlayPipe")); -#else - QString xdgRuntimePath = QProcessEnvironment::systemEnvironment().value(QLatin1String("XDG_RUNTIME_DIR")); - QString mumbleRuntimePath; - if (!xdgRuntimePath.isNull()) { - mumbleRuntimePath = QDir(xdgRuntimePath).absolutePath() + QLatin1String("/mumble/"); - } else { - mumbleRuntimePath = QLatin1String("/run/user/") + QString::number(getuid()) + QLatin1String("/mumble/"); + + char* c_pipepath = getAndCreateOverlayPipePath__(); + if (c_pipepath == NULL) { + perror("Could not create MumbleOverlayPipe."); + return; } - QDir mumbleRuntimeDir = QDir(mumbleRuntimePath); - mumbleRuntimeDir.mkpath("."); - QString pipepath = mumbleRuntimeDir.absoluteFilePath(QLatin1String("MumbleOverlayPipe")); - qWarning() << "connectToServer(" << pipepath << ")"; - qlsSocket->connectToServer(pipepath); -#endif + const std::string pipepath = c_pipepath; + + QString qPipepath = QString::fromUtf8(pipepath.data(), int(pipepath.size())); + qWarning() << "connectToServer(" << qPipepath << ")"; + qlsSocket->connectToServer(qPipepath); } QPainter painter(this);