I'm testing MQTT mosquitto library with this small program:
/*
compile using:
$ gcc -o libmosq libmosq.c -lmosquitto
*/
#include <stdio.h>
#include <mosquitto.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
struct mosquitto *mosq = NULL;
mosquitto_lib_init();
mosq = mosquitto_new(NULL, true, NULL);
if(!mosq) {
fprintf(stderr, "Error: Out of memory.\n");
exit(1);
}
mosquitto_username_pw_set(mosq, "user1", "passwd1");
int resultCode = mosquitto_connect(mosq, "localhost", 1883, 60);
if (resultCode != MOSQ_ERR_SUCCESS) {
fprintf(stderr, "connection error\n");
exit(1);
}
else {
printf("connection success\n");
}
// wait until control+C is done
sleep(1000000);
}
I'm running a MQTT broker (mosquitto broker version 1.6.10) in localhost at port 1883.
When I run the program I get "connection success"
and I see in the mosquitto log:
iot-mosquitto | 2021-10-06T10:16:11: New connection from 172.17.0.1 on port 1883.
iot-mosquitto | 2021-10-06T10:16:11: New client connected from 172.17.0.1 as auto-51085B64-A53B-DBE1-DBFB-A6D9D702B69C (p2, c1, k60, u'user1').
I understand that in this case the connection is correct. So far so good.
However, if I use a wrong user/pass (e.g. mosquitto_username_pw_set(mosq, "user1", "xxxxx")
) or if don't use user/pass (i.e. removing the mosquitto_username_pw_set()
map) I get in the mosquitto broker log:
iot-mosquitto | 2021-10-06T10:27:58: New connection from 172.17.0.1 on port 1883.
iot-mosquitto | 2021-10-06T10:27:58: Socket error on client <unknown>, disconnecting.
which is fine. The problem is that in my program I get "connection success"
instead of "connection error"
. In other words, I'm getting MOSQ_ERR_SUCCESS
as return value for mosquitto_connect()
instead of MOSQ_ERR_ERRNO
.
Looking to the MQTT broker traces, it is like my program gets connected (which would explain the MOSQ_ERR_SUCCESS
) but instanstanely it's disconnected...
How can I detect problems with user/password in the connection at connection time using the libmosquitto library, please?
Thanks in advance!
EDIT: I understand that there is some way to solve this, as mosquitto_sub (which I understand is based in the same library) is able to detect. Eg:
$ mosquitto_sub -p 1883 -t '#' -u user1 -P xxxxxx
Connection error: Connection Refused: not authorised.
I finally solved it using the following program:
/*
compile using:
$ gcc -o libmosq libmosq.c -lmosquitto
*/
#include <stdio.h>
#include <mosquitto.h>
#include <stdlib.h>
#include <unistd.h>
void connection_callback(struct mosquitto* mosq, void *obj, int rc)
{
if (rc) {
printf("connection error: %d (%s)\n", rc, mosquitto_connack_string(rc));
exit(1);
}
else {
printf("connection success\n");
}
}
int main(int argc, char *argv[])
{
struct mosquitto *mosq = NULL;
mosquitto_lib_init();
mosq = mosquitto_new(NULL, true, NULL);
if(!mosq) {
fprintf(stderr, "Error: Out of memory.\n");
exit(1);
}
mosquitto_connect_callback_set(mosq, connection_callback);
mosquitto_username_pw_set(mosq, "user1", "passwd1");
int resultCode = mosquitto_connect(mosq, "localhost", 1883, 60);
if (resultCode != MOSQ_ERR_SUCCESS) {
fprintf(stderr, "error calling mosquitto_connect\n");
exit(1);
}
int loop = mosquitto_loop_start(mosq);
if(loop != MOSQ_ERR_SUCCESS){
fprintf(stderr, "Unable to start loop: %i\n", loop);
exit(1);
}
// hang until control+C is done
sleep(1000000);
}
Main differences compared with the first version:
mosquitto_connect_callback_set()
to set a callback function for the connection eventmosquitto_loop_start()
. If I don't add this statement, the callback is not called upon connectionWith this program I get the following message when connection is successful:
connection success
and this one when password is wrong or if I remove the mosquitto_username_pw_set()
statement:
connection error: 5 (Connection Refused: not authorised.)