diff --git a/src/lib/client/Client.cpp b/src/lib/client/Client.cpp
index 375b6b750..9591e0864 100644
--- a/src/lib/client/Client.cpp
+++ b/src/lib/client/Client.cpp
@@ -13,6 +13,7 @@
#include "base/Log.h"
#include "base/TMethodJob.h"
#include "client/ServerProxy.h"
+#include "common/Settings.h"
#include "deskflow/AppUtil.h"
#include "deskflow/DeskflowException.h"
#include "deskflow/IPlatformScreen.h"
@@ -631,10 +632,10 @@ void Client::handleResume()
void Client::bindNetworkInterface(IDataSocket *socket) const
{
try {
- if (!m_args.m_deskflowAddress.empty()) {
- LOG_DEBUG1("bind to network interface: %s", m_args.m_deskflowAddress.c_str());
+ if (const auto address = Settings::value(Settings::Core::Interface).toString(); !address.isEmpty()) {
+ LOG_DEBUG1("bind to network interface: %s", qPrintable(address));
- NetworkAddress bindAddress(m_args.m_deskflowAddress);
+ NetworkAddress bindAddress(address.toStdString());
bindAddress.resolve();
socket->bind(bindAddress);
diff --git a/src/lib/deskflow/ArgParser.cpp b/src/lib/deskflow/ArgParser.cpp
index 4513c47f2..73aa69b30 100644
--- a/src/lib/deskflow/ArgParser.cpp
+++ b/src/lib/deskflow/ArgParser.cpp
@@ -122,9 +122,7 @@ bool ArgParser::parsePlatformArgs(deskflow::ArgsBase &argsBase, const int &argc,
bool ArgParser::parseGenericArgs(int argc, const char *const *argv, int &i) const
{
- if (isArg(i, argc, argv, "-a", "--address", 1)) {
- argsBase().m_deskflowAddress = argv[++i];
- } else if (isArg(i, argc, argv, "-d", "--debug", 1)) {
+ if (isArg(i, argc, argv, "-d", "--debug", 1)) {
// change logging level
argsBase().m_logFilter = argv[++i];
} else if (isArg(i, argc, argv, "-l", "--log", 1)) {
diff --git a/src/lib/deskflow/ArgsBase.h b/src/lib/deskflow/ArgsBase.h
index 0abf297f8..9e4e5da32 100644
--- a/src/lib/deskflow/ArgsBase.h
+++ b/src/lib/deskflow/ArgsBase.h
@@ -59,9 +59,6 @@ public:
/// @brief Will cause the application to exit with fail code when set to true
bool m_shouldExitFail = false;
- /// @brief Bind to this address
- std::string m_deskflowAddress;
-
/// @brief Should the connections be TLS encrypted
bool m_enableCrypto = false;
diff --git a/src/lib/deskflow/CMakeLists.txt b/src/lib/deskflow/CMakeLists.txt
index 68efb683c..d79d35e04 100644
--- a/src/lib/deskflow/CMakeLists.txt
+++ b/src/lib/deskflow/CMakeLists.txt
@@ -136,7 +136,7 @@ add_library(${lib_name} STATIC ${PLATFORM_CODE}
ipc/DaemonIpcServer.h
)
-target_link_libraries(${lib_name} PUBLIC Qt6::Core Qt6::Network)
+target_link_libraries(${lib_name} PUBLIC common Qt6::Core Qt6::Network)
if(WIN32)
target_link_libraries(${lib_name} PRIVATE ${cli11_lib} ${tomlPP_lib})
diff --git a/src/lib/deskflow/ClientApp.cpp b/src/lib/deskflow/ClientApp.cpp
index 04a48b187..f38278ca6 100644
--- a/src/lib/deskflow/ClientApp.cpp
+++ b/src/lib/deskflow/ClientApp.cpp
@@ -102,7 +102,6 @@ void ClientApp::help()
std::stringstream help;
help << "\n\nClient Mode:\n\n"
<< "Usage: " << kAppId << "-core client"
- << " [--address
]"
<< " [--yscroll ]"
<< " [--sync-language]"
<< " [--invert-scroll]"
@@ -113,7 +112,6 @@ void ClientApp::help()
<< "\n\n"
<< "Connect to a " << kAppName << " mouse/keyboard sharing server.\n"
<< "\n"
- << " -a, --address local network interface address.\n"
<< s_helpGeneralArgs << " --yscroll defines the vertical scrolling delta,\n"
<< " which is 120 by default.\n"
<< " --sync-language enable language synchronization.\n"
diff --git a/src/lib/deskflow/CoreArgParser.cpp b/src/lib/deskflow/CoreArgParser.cpp
index cefb14059..b37df4cef 100644
--- a/src/lib/deskflow/CoreArgParser.cpp
+++ b/src/lib/deskflow/CoreArgParser.cpp
@@ -24,7 +24,7 @@ CoreArgParser::CoreArgParser(const QStringList &args)
m_parser.parse(args);
m_parser.setApplicationDescription(kAppDescription);
- m_helpText = m_parser.helpText().replace("", QString("%1-core").arg(kAppId));
+ m_helpText = m_parser.helpText().replace("", s_appName);
m_helpText.replace("[options] coremode", "coremode [options]");
}
@@ -48,6 +48,14 @@ void CoreArgParser::parse()
if (m_parser.isSet(CoreArgs::configOption)) {
Settings::setSettingFile(m_parser.value(CoreArgs::configOption));
}
+
+ if (m_parser.isSet(CoreArgs::interfaceOption)) {
+ Settings::setValue(Settings::Core::Interface, m_parser.value(CoreArgs::interfaceOption));
+ }
+
+ if (m_parser.isSet(CoreArgs::portOption)) {
+ Settings::setValue(Settings::Core::Port, m_parser.value(CoreArgs::portOption));
+ }
}
[[noreturn]] void CoreArgParser::showHelpText() const
diff --git a/src/lib/deskflow/CoreArgs.h b/src/lib/deskflow/CoreArgs.h
index fe71cccf6..8e1d96e01 100644
--- a/src/lib/deskflow/CoreArgs.h
+++ b/src/lib/deskflow/CoreArgs.h
@@ -18,5 +18,13 @@ struct CoreArgs
inline static const auto configOption = QCommandLineOption(
{"s", "settings"}, "override configuration file to use", "configFile"
); // use -c later, now avoid breaking the serverApp args.
- inline static const auto options = {helpOption, versionOption, configOption};
+ inline static const auto interfaceOption = QCommandLineOption(
+ {"i", "interface"},
+ "Use a specific interface for the connection. Instead of any address in client mode or listening on all "
+ "addresses in server mode address.\n address must be the IP address or hostname of an interface on the system.",
+ "address"
+ );
+ inline static const auto portOption =
+ QCommandLineOption({"p", "port"}, "Port to use in place of default port", "port");
+ inline static const auto options = {helpOption, versionOption, configOption, interfaceOption, portOption};
};
diff --git a/src/lib/deskflow/ServerApp.cpp b/src/lib/deskflow/ServerApp.cpp
index 23af03f52..fef66f96c 100644
--- a/src/lib/deskflow/ServerApp.cpp
+++ b/src/lib/deskflow/ServerApp.cpp
@@ -13,6 +13,7 @@
#include "base/Log.h"
#include "base/Path.h"
#include "common/ExitCodes.h"
+#include "common/Settings.h"
#include "deskflow/App.h"
#include "deskflow/ArgParser.h"
#include "deskflow/Screen.h"
@@ -86,9 +87,9 @@ void ServerApp::parseArgs(int argc, const char *const *argv)
bye(s_exitArgs);
}
} else {
- if (!args().m_deskflowAddress.empty()) {
+ if (const auto address = Settings::value(Settings::Core::Interface).toString(); !address.isEmpty()) {
try {
- *m_deskflowAddress = NetworkAddress(args().m_deskflowAddress, kDefaultPort);
+ *m_deskflowAddress = NetworkAddress(address.toStdString(), kDefaultPort);
m_deskflowAddress->resolve();
} catch (SocketAddressException &e) {
LOG_CRIT("%s: %s" BYE, args().m_pname, e.what(), args().m_pname);
@@ -104,14 +105,12 @@ void ServerApp::help()
help << "\n\nServer Mode:\n\n"
<< "Usage: " << kAppId << "-core server"
<< " --config "
- << " [--address ]"
#if WINAPI_XWINDOWS
<< " [--display ]"
#endif
<< s_helpCommonArgs << "\n"
- << " -a, --address listen for clients on the given address.\n"
<< " -c, --config path of the configuration file\n"
<< s_helpGeneralArgs
<< " --disable-client-cert-check disable client SSL certificate \n"
@@ -125,15 +124,7 @@ void ServerApp::help()
<< "* marks defaults.\n"
- << s_helpNoWayland
-
- << "\n"
- << "The argument for --address is of the form: [][:]. "
- "The\n"
- << "hostname must be the address or hostname of an interface on the "
- << "system.\n"
- << "The default is to listen on all interfaces. The port overrides the\n"
- << "default port, " << kDefaultPort << ".\n";
+ << s_helpNoWayland;
LOG_PRINT("%s", help.str().c_str());
}
diff --git a/src/lib/gui/core/CoreProcess.cpp b/src/lib/gui/core/CoreProcess.cpp
index a887f4ffd..50f0d3682 100644
--- a/src/lib/gui/core/CoreProcess.cpp
+++ b/src/lib/gui/core/CoreProcess.cpp
@@ -488,12 +488,6 @@ bool CoreProcess::addServerArgs(QStringList &args)
return false;
}
- // the address arg is dual purpose; when in listening mode, it's the address
- // that the server listens on. when tcp sockets are inverted, it connects to
- // that address. this is a bit confusing, and there should be probably be
- // different args for different purposes.
- args << "--address" << correctedInterface();
-
args << "-c" << configFilename;
qInfo("core config file: %s", qPrintable(configFilename));
// bizarrely, the tls cert path arg was being given to the core client.
@@ -650,13 +644,6 @@ void CoreProcess::checkOSXNotification(const QString &line)
}
#endif
-QString CoreProcess::correctedInterface() const
-{
- const QString interface = wrapIpv6(Settings::value(Settings::Core::Interface).toString());
- const auto port = Settings::value(Settings::Core::Port).toString();
- return QStringLiteral("%1:%2").arg(interface, port);
-}
-
QString CoreProcess::correctedAddress() const
{
return wrapIpv6(m_address);
diff --git a/src/lib/gui/core/CoreProcess.h b/src/lib/gui/core/CoreProcess.h
index 82de404d7..daabf3447 100644
--- a/src/lib/gui/core/CoreProcess.h
+++ b/src/lib/gui/core/CoreProcess.h
@@ -126,7 +126,6 @@ private:
void checkLogLine(const QString &line);
bool checkSecureSocket(const QString &line);
void handleLogLines(const QString &text);
- QString correctedInterface() const;
QString correctedAddress() const;
QString requestDaemonLogPath();
void persistLogDir() const;
diff --git a/src/unittests/deskflow/ArgParserTests.cpp b/src/unittests/deskflow/ArgParserTests.cpp
index 74c78413a..1f2a5c060 100644
--- a/src/unittests/deskflow/ArgParserTests.cpp
+++ b/src/unittests/deskflow/ArgParserTests.cpp
@@ -162,17 +162,6 @@ void ArgParserTests::assembleCommand()
QCOMPARE(command, "\"stub1 space\" stub2 \"stub3 space\"");
}
-void ArgParserTests::server_setAddress()
-{
- deskflow::ServerArgs serverArgs;
- const int argc = 3;
- const char *kAddressCmd[argc] = {"stub", "--address", "mock_address"};
-
- m_parser.parseServerArgs(serverArgs, argc, kAddressCmd);
-
- QCOMPARE(serverArgs.m_deskflowAddress, "mock_address");
-}
-
void ArgParserTests::server_setConfigFile()
{
deskflow::ServerArgs serverArgs;
diff --git a/src/unittests/deskflow/ArgParserTests.h b/src/unittests/deskflow/ArgParserTests.h
index 9af31c623..eddf3f550 100644
--- a/src/unittests/deskflow/ArgParserTests.h
+++ b/src/unittests/deskflow/ArgParserTests.h
@@ -22,7 +22,6 @@ private Q_SLOTS:
void getArgv();
void assembleCommand();
void serverArgs();
- void server_setAddress();
void server_setConfigFile();
void server_unexpectedParam();
void clientArgs();
diff --git a/src/unittests/deskflow/CMakeLists.txt b/src/unittests/deskflow/CMakeLists.txt
index 418ea68be..ce9f0f623 100644
--- a/src/unittests/deskflow/CMakeLists.txt
+++ b/src/unittests/deskflow/CMakeLists.txt
@@ -13,6 +13,14 @@ create_test(
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/lib/deskflow"
)
+create_test(
+ NAME CoreArgParserTests
+ DEPENDS app
+ LIBS ${extra_libs}
+ SOURCE CoreArgParserTests.cpp
+ WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/lib/deskflow"
+)
+
create_test(
NAME ClipboardTests
DEPENDS app
diff --git a/src/unittests/deskflow/CoreArgParserTests.cpp b/src/unittests/deskflow/CoreArgParserTests.cpp
new file mode 100644
index 000000000..bdf9fe356
--- /dev/null
+++ b/src/unittests/deskflow/CoreArgParserTests.cpp
@@ -0,0 +1,63 @@
+/*
+ * Deskflow -- mouse and keyboard sharing utility
+ * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello
+ * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
+ */
+
+#include "CoreArgParserTests.h"
+#include "common/Settings.h"
+#include "deskflow/CoreArgParser.h"
+
+void CoreArgParserTests::initTestCase()
+{
+ QDir dir;
+ QVERIFY(dir.mkpath(m_settingsPath));
+
+ QFile oldSettings(m_settingsFile);
+ if (oldSettings.exists())
+ oldSettings.remove();
+
+ Settings::setSettingFile(m_settingsFile);
+}
+
+void CoreArgParserTests::interfaceLong()
+{
+ QStringList args = {"stub", "client", "--interface", "mock_address"};
+
+ CoreArgParser parser(args);
+ parser.parse();
+
+ QCOMPARE(Settings::value(Settings::Core::Interface).toString(), "mock_address");
+}
+
+void CoreArgParserTests::interfaceShort()
+{
+ QStringList args = {"stub", "client", "-i", "address"};
+
+ CoreArgParser parser(args);
+ parser.parse();
+
+ QCOMPARE(Settings::value(Settings::Core::Interface).toString(), "address");
+}
+
+void CoreArgParserTests::portLong()
+{
+ QStringList args = {"stub", "client", "--port", "28771"};
+
+ CoreArgParser parser(args);
+ parser.parse();
+
+ QCOMPARE(Settings::value(Settings::Core::Port).toInt(), 28771);
+}
+
+void CoreArgParserTests::portShort()
+{
+ QStringList args = {"stub", "client", "--p", "18768"};
+
+ CoreArgParser parser(args);
+ parser.parse();
+
+ QCOMPARE(Settings::value(Settings::Core::Port).toInt(), 18768);
+}
+
+QTEST_MAIN(CoreArgParserTests)
diff --git a/src/unittests/deskflow/CoreArgParserTests.h b/src/unittests/deskflow/CoreArgParserTests.h
new file mode 100644
index 000000000..071316a06
--- /dev/null
+++ b/src/unittests/deskflow/CoreArgParserTests.h
@@ -0,0 +1,25 @@
+/*
+ * Deskflow -- mouse and keyboard sharing utility
+ * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello
+ * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
+ */
+
+#include "deskflow/CoreArgParser.h"
+
+#include
+
+class CoreArgParserTests : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void initTestCase();
+ // Test are run in order top to bottom
+ void interfaceLong();
+ void interfaceShort();
+ void portLong();
+ void portShort();
+
+private:
+ inline static const QString m_settingsPath = QStringLiteral("tmp/test");
+ inline static const QString m_settingsFile = QStringLiteral("%1/Deskflow.conf").arg(m_settingsPath);
+};