Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extra update connect options callback call after 3 seconds after reconnect attempt #1513

Open
elzbieta-nowak-kubat opened this issue Aug 30, 2024 · 2 comments

Comments

@elzbieta-nowak-kubat
Copy link

Describe the bug

When using update connect options callback (set by MQTTAsync_setUpdateConnectOptions), this callback is fired to often: once before reconnect (that is ok) and the second time after 3 secons (that is not correct). If there is the log informing user about reconnect in the callback user gets wrongly informed in case of this extra call.

The problem happens because MQTTAsync_startConnectRetry (where lastConnectionFailedTime and currentInterval are set) is called very late after MQTTProtocol_connect. This is because socket is not ready for some time (> 3 second most of the time) for checking of TCP connection completion. In meantime MQTTAsync_checkTimeouts function body is executed every 3 seconds, keeping eye on the reconnection time. So when time to reconnect comes (based on lastConnectionFailedTime and currentInterval), update connect options callback (the one set by call MQTTAsync_setUpdateConnectOptions) is fired and reconnect initialized (connect queued and executed (MQTTAsync_processCommand)) but then fired again after 3 seconds because lastConnectionFailedTime won't make to be set to new value. Usually the second call of the callback is not followed by real connect because connect_state is usually TCP_IN_PROGRESS, but I noticed once situation that it was no the case and the second connect was attempted.

To Reproduce
Set automaticReconnect connection option and set callback using MQTTAsync_setUpdateConnectOptions

My example using paho cpp:

#include <iostream>
#include <cstdlib>
#include <string>
#include <thread>
#include <atomic>
#include <chrono>
#include <cstring>
#include "mqtt/async_client.h"

using namespace std;

const string DFLT_SERVER_ADDRESS	{ "mqtt://localhost:1883" };
const string CLIENT_ID				{ "paho_cpp_update_conn_opts_enk" };


/////////////////////////////////////////////////////////////////////////////

class MQTTCallback : public virtual mqtt::callback
{
public:
	void connected(std::string const& param) override
	{
		std::string message = "MQTT connected: " + param;
		cout << message << endl;
	}

	void connection_lost(const string& cause) override {
		cout << "\nConnection lost" << endl;
		if (!cause.empty())
			cout << "\tcause: " << cause << endl;
	}

	void delivery_complete(mqtt::delivery_token_ptr tok) override {
		cout << "\tDelivery complete for token: "
			<< (tok ? tok->get_message_id() : -1) << endl;
	}
};

/////////////////////////////////////////////////////////////////////////////

int main(int argc, char* argv[])
{
	string	address  = (argc > 1) ? string(argv[1]) : DFLT_SERVER_ADDRESS,
			clientID = (argc > 2) ? string(argv[2]) : CLIENT_ID;

	cout << "Initializing for server '" << address << "'..." << endl;
	auto createOptions = mqtt::create_options_builder()
		.mqtt_version(MQTTVERSION_5)
		.send_while_disconnected(false, false)
		.max_buffered_messages(1000)
		.delete_oldest_messages(false)
		.restore_messages(false)
		.persist_qos0(false)
		.finalize();

	mqtt::async_client client(address, clientID, createOptions);

	MQTTCallback cb;
	client.set_callback(cb);
	client.set_disconnected_handler([](const mqtt::properties&, mqtt::ReasonCode reason) {
		cout << "*** Disconnected. Reason: " << reason << " ***" << endl;
	});

	client.set_update_connection_handler(
		[](mqtt::connect_data& connData) {
			cout << "Reconnecting " << endl;
			return true;
		}
	);

	auto connOpts = mqtt::connect_options::v5();
	connOpts.set_keep_alive_interval(60);
	connOpts.set_connect_timeout(30);
	connOpts.set_clean_start(true);
	connOpts.set_automatic_reconnect(true);

	cout << "  ...OK, Initialized" << endl;

	try {
		cout << "\nConnecting..." << endl;
		mqtt::token_ptr conntok = client.connect(connOpts);
		cout << "Waiting for the connection..." << endl;
	}
	catch (const mqtt::exception& exc) {
		cerr << exc.what() << endl;
	}

	while (std::tolower(std::cin.get()) != 'q');

	try {
		if (client.is_connected())
		{
			std::cout << "\nDisconnecting from the MQTT server..." << std::flush;
			client.disconnect()->wait();
			std::cout << "OK" << std::endl;
		}
	}
	catch (const mqtt::exception& exc) {
		std::cerr << exc << std::endl;
		return 1;
	}

 	return 0;
}

Expected behavior
Update connect options callback is fired once per reconnect attempt.

Screenshots
N/A

Log files
N/A

** Environment (please complete the following information):**
Windows 11

Additional context
N/A

@elzbieta-nowak-kubat
Copy link
Author

To reproduce set localhost as brokerAddress, no TLS. Broker is off.

@jumoog
Copy link
Contributor

jumoog commented Sep 5, 2024

its a know issue #530

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants