From 538108b192f00f7d5e89370301f978b6df8b3623 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 21 Mar 2025 17:37:30 +0000 Subject: [PATCH] Add optional MQTT authentication. --- Conf.cpp | 24 ++++++++++++++++++++++++ Conf.h | 8 +++++++- DMRGateway.cpp | 4 ++-- DMRGateway.ini | 3 +++ DMRGateway.vcxproj | 18 ++++++++++++++---- DMRGateway.vcxproj.filters | 6 ++++++ MQTTConnection.cpp | 8 +++++++- MQTTConnection.h | 5 ++++- Version.h | 2 +- 9 files changed, 68 insertions(+), 10 deletions(-) diff --git a/Conf.cpp b/Conf.cpp index 44e2848..dc9083c 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -183,6 +183,9 @@ m_mqttAddress("127.0.0.1"), m_mqttPort(1883U), m_mqttKeepalive(60U), m_mqttName("dmr-gateway"), +m_mqttAuthEnabled(false), +m_mqttUsername(), +m_mqttPassword(), m_dynamicTGControlEnabled(false), m_remoteCommandsEnabled(false) { @@ -989,6 +992,12 @@ bool CConf::read() m_mqttKeepalive = (unsigned int)::atoi(value); else if (::strcmp(key, "Name") == 0) m_mqttName = value; + else if (::strcmp(key, "Auth") == 0) + m_mqttAuthEnabled = ::atoi(value) == 1; + else if (::strcmp(key, "Username") == 0) + m_mqttUsername = value; + else if (::strcmp(key, "Password") == 0) + m_mqttPassword = value; } else if (section == SECTION::DYNAMIC_TG_CONTROL) { if (::strcmp(key, "Enable") == 0) m_dynamicTGControlEnabled = ::atoi(value) == 1; @@ -1696,6 +1705,21 @@ std::string CConf::getMQTTName() const return m_mqttName; } +bool CConf::getMQTTAuthEnabled() const +{ + return m_mqttAuthEnabled; +} + +std::string CConf::getMQTTUsername() const +{ + return m_mqttUsername; +} + +std::string CConf::getMQTTPassword() const +{ + return m_mqttPassword; +} + bool CConf::getDynamicTGControlEnabled() const { return m_dynamicTGControlEnabled; diff --git a/Conf.h b/Conf.h index 12d6b77..22f4c98 100644 --- a/Conf.h +++ b/Conf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016,2017,2019,2020,2023 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017,2019,2020,2023,2025 by Jonathan Naylor G4KLX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -238,6 +238,9 @@ public: unsigned short getMQTTPort() const; unsigned int getMQTTKeepalive() const; std::string getMQTTName() const; + bool getMQTTAuthEnabled() const; + std::string getMQTTUsername() const; + std::string getMQTTPassword() const; // The Dynamic TG Control section bool getDynamicTGControlEnabled() const; @@ -395,6 +398,9 @@ private: unsigned short m_mqttPort; unsigned int m_mqttKeepalive; std::string m_mqttName; + bool m_mqttAuthEnabled; + std::string m_mqttUsername; + std::string m_mqttPassword; bool m_dynamicTGControlEnabled; diff --git a/DMRGateway.cpp b/DMRGateway.cpp index 765d399..a189c98 100644 --- a/DMRGateway.cpp +++ b/DMRGateway.cpp @@ -77,7 +77,7 @@ static CDMRGateway* gateway = nullptr; const char* HEADER1 = "This software is for use on amateur radio networks only,"; const char* HEADER2 = "it is to be used for educational purposes only. Its use on"; const char* HEADER3 = "commercial networks is strictly prohibited."; -const char* HEADER4 = "Copyright(C) 2017-2024 by Jonathan Naylor, G4KLX and others"; +const char* HEADER4 = "Copyright(C) 2017-2025 by Jonathan Naylor, G4KLX and others"; int main(int argc, char** argv) { @@ -373,7 +373,7 @@ int CDMRGateway::run() if (m_conf.getRemoteCommandsEnabled()) subscriptions.push_back(std::make_pair("command", CDMRGateway::onCommand)); - m_mqtt = new CMQTTConnection(m_conf.getMQTTAddress(), m_conf.getMQTTPort(), m_conf.getMQTTName(), subscriptions, m_conf.getMQTTKeepalive()); + m_mqtt = new CMQTTConnection(m_conf.getMQTTAddress(), m_conf.getMQTTPort(), m_conf.getMQTTName(), m_conf.getMQTTAuthEnabled(), m_conf.getMQTTUsername(), m_conf.getMQTTPassword(), subscriptions, m_conf.getMQTTKeepalive()); ret = m_mqtt->open(); if (!ret) return 1; diff --git a/DMRGateway.ini b/DMRGateway.ini index 37ffbff..0092169 100644 --- a/DMRGateway.ini +++ b/DMRGateway.ini @@ -150,6 +150,9 @@ Suffix=3 Address=127.0.0.1 Port=1883 Keepalive=60 +Auth=0 +Username=mmdvm +Password=mmdvm Name=dmr-gateway [Dynamic TG Control] diff --git a/DMRGateway.vcxproj b/DMRGateway.vcxproj index db7d4ec..e29eab9 100644 --- a/DMRGateway.vcxproj +++ b/DMRGateway.vcxproj @@ -88,11 +88,13 @@ Level3 Disabled _CRT_SECURE_NO_WARNINGS;HAVE_LOG_H + C:\Program Files\mosquitto\devel;C:\Program Files Console true - ws2_32.lib;%(AdditionalDependencies) + ws2_32.lib;mosquitto.lib;%(AdditionalDependencies) + C:\Program Files\mosquitto\devel prebuild.cmd @@ -105,11 +107,13 @@ Level3 Disabled _CRT_SECURE_NO_WARNINGS;HAVE_LOG_H + C:\Program Files\mosquitto\devel;C:\Program Files Console true - ws2_32.lib;%(AdditionalDependencies) + ws2_32.lib;mosquitto.lib;%(AdditionalDependencies) + C:\Program Files\mosquitto\devel prebuild.cmd @@ -128,13 +132,15 @@ true true _CRT_SECURE_NO_WARNINGS;HAVE_LOG_H + C:\Program Files\mosquitto\devel;C:\Program Files Console true true true - ws2_32.lib;%(AdditionalDependencies) + ws2_32.lib;mosquitto.lib;%(AdditionalDependencies) + C:\Program Files\mosquitto\devel prebuild.cmd @@ -149,13 +155,15 @@ true true _CRT_SECURE_NO_WARNINGS;HAVE_LOG_H + C:\Program Files\mosquitto\devel;C:\Program Files Console true true true - ws2_32.lib;%(AdditionalDependencies) + ws2_32.lib;mosquitto.lib;%(AdditionalDependencies) + C:\Program Files\mosquitto\devel prebuild.cmd @@ -183,6 +191,7 @@ + @@ -230,6 +239,7 @@ + diff --git a/DMRGateway.vcxproj.filters b/DMRGateway.vcxproj.filters index 66c48ee..821629d 100644 --- a/DMRGateway.vcxproj.filters +++ b/DMRGateway.vcxproj.filters @@ -149,6 +149,9 @@ Header Files + + Header Files + @@ -280,5 +283,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/MQTTConnection.cpp b/MQTTConnection.cpp index 3da73e6..c102bf1 100644 --- a/MQTTConnection.cpp +++ b/MQTTConnection.cpp @@ -23,10 +23,13 @@ #include #include -CMQTTConnection::CMQTTConnection(const std::string& host, unsigned short port, const std::string& name, const std::vector>& subs, unsigned int keepalive, MQTT_QOS qos) : +CMQTTConnection::CMQTTConnection(const std::string& host, unsigned short port, const std::string& name, const bool authEnabled, const std::string& username, const std::string& password, const std::vector>& subs, unsigned int keepalive, MQTT_QOS qos) : m_host(host), m_port(port), m_name(name), +m_authEnabled(authEnabled), +m_username(username), +m_password(password), m_subs(subs), m_keepalive(keepalive), m_qos(qos), @@ -59,6 +62,9 @@ bool CMQTTConnection::open() return false; } + if (m_authEnabled) + ::mosquitto_username_pw_set(m_mosq, m_username.c_str(), m_password.c_str()); + ::mosquitto_connect_callback_set(m_mosq, onConnect); ::mosquitto_subscribe_callback_set(m_mosq, onSubscribe); ::mosquitto_message_callback_set(m_mosq, onMessage); diff --git a/MQTTConnection.h b/MQTTConnection.h index 9891b21..9f718da 100644 --- a/MQTTConnection.h +++ b/MQTTConnection.h @@ -32,7 +32,7 @@ enum class MQTT_QOS : int { class CMQTTConnection { public: - CMQTTConnection(const std::string& host, unsigned short port, const std::string& name, const std::vector>& subs, unsigned int keepalive, MQTT_QOS qos = MQTT_QOS::EXACTLY_ONCE); + CMQTTConnection(const std::string& host, unsigned short port, const std::string& name, const bool authEnabled, const std::string& username, const std::string& password, const std::vector>& subs, unsigned int keepalive, MQTT_QOS qos = MQTT_QOS::EXACTLY_ONCE); ~CMQTTConnection(); bool open(); @@ -47,6 +47,9 @@ private: std::string m_host; unsigned short m_port; std::string m_name; + bool m_authEnabled; + std::string m_username; + std::string m_password; std::vector> m_subs; unsigned int m_keepalive; MQTT_QOS m_qos; diff --git a/Version.h b/Version.h index 89bcaee..bdf647f 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20250315"; +const char* VERSION = "20250321"; #endif