Fix: Prevent access to nullptr object when reconnecting to mqtt

It could occour when saving the settings via the web ui
This commit is contained in:
Thomas Basler 2023-08-03 18:46:28 +02:00
parent 832df5a80e
commit 0bdee6ec99
2 changed files with 42 additions and 5 deletions

View File

@ -5,6 +5,7 @@
#include <MqttSubscribeParser.h> #include <MqttSubscribeParser.h>
#include <Ticker.h> #include <Ticker.h>
#include <espMqttClient.h> #include <espMqttClient.h>
#include <mutex>
class MqttSettingsClass { class MqttSettingsClass {
public: public:
@ -37,6 +38,7 @@ private:
String willTopic; String willTopic;
Ticker mqttReconnectTimer; Ticker mqttReconnectTimer;
MqttSubscribeParser _mqttSubscribeParser; MqttSubscribeParser _mqttSubscribeParser;
std::mutex _clientLock;
}; };
extern MqttSettingsClass MqttSettings; extern MqttSettingsClass MqttSettings;

View File

@ -32,22 +32,31 @@ void MqttSettingsClass::onMqttConnect(bool sessionPresent)
const CONFIG_T& config = Configuration.get(); const CONFIG_T& config = Configuration.get();
publish(config.Mqtt_LwtTopic, config.Mqtt_LwtValue_Online); publish(config.Mqtt_LwtTopic, config.Mqtt_LwtValue_Online);
std::lock_guard<std::mutex> lock(_clientLock);
if (mqttClient != nullptr) {
for (const auto& cb : _mqttSubscribeParser.get_callbacks()) { for (const auto& cb : _mqttSubscribeParser.get_callbacks()) {
mqttClient->subscribe(cb.topic.c_str(), cb.qos); mqttClient->subscribe(cb.topic.c_str(), cb.qos);
} }
} }
}
void MqttSettingsClass::subscribe(const String& topic, uint8_t qos, const espMqttClientTypes::OnMessageCallback& cb) void MqttSettingsClass::subscribe(const String& topic, uint8_t qos, const espMqttClientTypes::OnMessageCallback& cb)
{ {
_mqttSubscribeParser.register_callback(topic.c_str(), qos, cb); _mqttSubscribeParser.register_callback(topic.c_str(), qos, cb);
std::lock_guard<std::mutex> lock(_clientLock);
if (mqttClient != nullptr) {
mqttClient->subscribe(topic.c_str(), qos); mqttClient->subscribe(topic.c_str(), qos);
} }
}
void MqttSettingsClass::unsubscribe(const String& topic) void MqttSettingsClass::unsubscribe(const String& topic)
{ {
_mqttSubscribeParser.unregister_callback(topic.c_str()); _mqttSubscribeParser.unregister_callback(topic.c_str());
std::lock_guard<std::mutex> lock(_clientLock);
if (mqttClient != nullptr) {
mqttClient->unsubscribe(topic.c_str()); mqttClient->unsubscribe(topic.c_str());
} }
}
void MqttSettingsClass::onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) void MqttSettingsClass::onMqttDisconnect(espMqttClientTypes::DisconnectReason reason)
{ {
@ -97,6 +106,12 @@ void MqttSettingsClass::performConnect()
using std::placeholders::_4; using std::placeholders::_4;
using std::placeholders::_5; using std::placeholders::_5;
using std::placeholders::_6; using std::placeholders::_6;
std::lock_guard<std::mutex> lock(_clientLock);
if (mqttClient == nullptr) {
return;
}
MessageOutput.println("Connecting to MQTT..."); MessageOutput.println("Connecting to MQTT...");
const CONFIG_T& config = Configuration.get(); const CONFIG_T& config = Configuration.get();
willTopic = getPrefix() + config.Mqtt_LwtTopic; willTopic = getPrefix() + config.Mqtt_LwtTopic;
@ -132,6 +147,10 @@ void MqttSettingsClass::performDisconnect()
{ {
const CONFIG_T& config = Configuration.get(); const CONFIG_T& config = Configuration.get();
publish(config.Mqtt_LwtTopic, config.Mqtt_LwtValue_Offline); publish(config.Mqtt_LwtTopic, config.Mqtt_LwtValue_Offline);
std::lock_guard<std::mutex> lock(_clientLock);
if (mqttClient == nullptr) {
return;
}
mqttClient->disconnect(); mqttClient->disconnect();
} }
@ -147,6 +166,10 @@ void MqttSettingsClass::performReconnect()
bool MqttSettingsClass::getConnected() bool MqttSettingsClass::getConnected()
{ {
std::lock_guard<std::mutex> lock(_clientLock);
if (mqttClient == nullptr) {
return false;
}
return mqttClient->connected(); return mqttClient->connected();
} }
@ -157,6 +180,11 @@ String MqttSettingsClass::getPrefix()
void MqttSettingsClass::publish(const String& subtopic, const String& payload) void MqttSettingsClass::publish(const String& subtopic, const String& payload)
{ {
std::lock_guard<std::mutex> lock(_clientLock);
if (mqttClient == nullptr) {
return;
}
String topic = getPrefix(); String topic = getPrefix();
topic += subtopic; topic += subtopic;
@ -168,6 +196,10 @@ void MqttSettingsClass::publish(const String& subtopic, const String& payload)
void MqttSettingsClass::publishGeneric(const String& topic, const String& payload, bool retain, uint8_t qos) void MqttSettingsClass::publishGeneric(const String& topic, const String& payload, bool retain, uint8_t qos)
{ {
std::lock_guard<std::mutex> lock(_clientLock);
if (mqttClient == nullptr) {
return;
}
mqttClient->publish(topic.c_str(), qos, retain, payload.c_str()); mqttClient->publish(topic.c_str(), qos, retain, payload.c_str());
} }
@ -181,8 +213,11 @@ void MqttSettingsClass::init()
void MqttSettingsClass::createMqttClientObject() void MqttSettingsClass::createMqttClientObject()
{ {
if (mqttClient != nullptr) std::lock_guard<std::mutex> lock(_clientLock);
if (mqttClient != nullptr) {
delete mqttClient; delete mqttClient;
mqttClient = nullptr;
}
const CONFIG_T& config = Configuration.get(); const CONFIG_T& config = Configuration.get();
if (config.Mqtt_Tls) { if (config.Mqtt_Tls) {
mqttClient = static_cast<MqttClient*>(new espMqttClientSecure); mqttClient = static_cast<MqttClient*>(new espMqttClientSecure);