Hi,
I am trying to send a specific message type using the MQTT protocol. I am using the paho.mqtt.c library, and my broker is RabbitMQ 3.6.12, running Erlang 20.0. I am working on a virtual machine running CentOS 6.9. I first tried doing it by creating a struct for my specific message type, like so :
typedef struct frame1
{
char* str;
int entier;
} frame1;
This is my publisher program :
int main(int argc, char* argv[])
{
frame1* payload = (frame1*)malloc(sizeof(frame1));
*p_entier = atoi(argv[2]);
p_str = argv[1];
//int p_entier = atoi(argv[2]);
//char* p_str = argv[1];
//payload->str = (char*)malloc(100*sizeof(char));
//payload->str = p_str;
//payload->entier = (int*)malloc(sizeof(int));
//payload->entier = p_entier;
MQTTClient publisher;
MQTTClient_connectOptions connexion = MQTTClient_connectOptions_initializer;
MQTTClient_message msg = msg_creation(payload,sizeof(frame1),0,0);
int rc;
MQTTClient_create(&publisher, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
connexion.cleansession = 1;
MQTTClient_setCallbacks(publisher, NULL, connlost, frame_1_arrvd, NULL);
if ((rc = MQTTClient_connect(publisher,&connexion)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
}
printf("message à envoyer : \n");
print_frame1(msg.payload);
MQTTClient_publishMessage(publisher, TOPIC,&msg,NULL);
printf("Message sent!\n");
MQTTClient_disconnect(publisher,10000);
MQTTClient_destroy(&publisher);
return rc;
}
Here is the print_frame1
function :
void print_frame1(frame1* F)
{
printf("%s : %d\n",F->str,F->entier);
}
and msg_creation
:
MQTTClient_message msg_creation(void* payload, int length, int qos, int retained)
{
MQTTClient_message pubmsg = MQTTClient_message_initializer;
pubmsg.payload = payload;
pubmsg.payloadlen = length;
pubmsg.qos = qos;
pubmsg.retained = retained;
return pubmsg;
}
and the function used to receive the messages :
int frame_1_arrvd(void* context, char* topicName, int topicLen, MQTTClient_message* msg)
{
int i;
print_frame1(msg->payload);
frame1* payload; //= (frame1*)malloc(sizeof(frame1));
payload->str = (char*)malloc(100*sizeof(char));
payload = msg->payload;
print_frame1(payload);
printf("New message!\n in topic %s:\n", topicName);
printf("%s : %d\n",payload->str,payload->entier);*/
MQTTClient_freeMessage(&msg);
MQTTClient_free(topicName);
return 1;
}
The parts I commented are things I tried but didn't work any better. What I mean when I say that it doesn't work is that the first print_frame1
on the receiver side results in a segmentation fault (core dumped)
. It appears something is received, but not the expected string. After investigating the core dumped, I tried replacing %s
by %c
in the print_frame1
function, and I didn't get a segmentation fault anymore, but rather a character that had nothing to do with the string that was supposed to be sent (like, I would usually get a number or a special character).
At first I thought maybe the problem came from the way I created the message, but print_frame1(msg.payload)
in the publisher code works fine, so I assume the message is correctly created, and yet it is not correctly sent or received.
Before asking this question, I also tried using JSON to create my specific message type. I installed cJSON (from here), and tried creating my frame this way :
cJSON* create_frame1(char* str, int entier)
{
cJSON* frame1 = NULL;
frame1 = cJSON_CreateObject();
cJSON_AddStringToObject(frame1,"string",str);
cJSON_AddNumberToObject(frame1,"entier", entier);
return frame1;
}
And I changed my publisher to this :
int main(int argc, char* argv[])
{
int p_entier = atoi(argv[2]);
char* p_str = argv[1];
cJSON* payload = create_frame1(p_str,p_entier);
print_frame1(payload);
MQTTClient publisher;
MQTTClient_connectOptions connexion = MQTTClient_connectOptions_initializer;
MQTTClient_message msg = msg_creation(payload,sizeof(payload),0,0);
int rc;
MQTTClient_create(&publisher, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
connexion.cleansession = 1;
MQTTClient_setCallbacks(publisher, NULL, connlost, frame_1_arrvd, NULL);
if ((rc = MQTTClient_connect(publisher,&connexion)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
}
printf("message à envoyer : \n");
print_frame1(msg.payload);
MQTTClient_publishMessage(publisher, TOPIC,&msg,NULL);
printf("Message sent!\n");
MQTTClient_disconnect(publisher,10000);
MQTTClient_destroy(&publisher);
return rc;
}
I also modified the print_frame1
function :
void print_frame1(cJSON* frame1)
{
//printf("%s",cJSON_GetObjectItem(frame1,"string"));
//printf(" %d\n",cJSON_GetObjectItem(frame1,"entier"));
char * str = cJSON_Print(frame1);
printf("%s\n",str);
//printf("%s %d \n",str,entier);
}
and the receiving part :
int frame_1_arrvd(void* context, char* topicName, int topicLen, MQTTClient_message* msg)
{
int i;
print_frame1(msg->payload);
cJSON* payload_ptr;
payload_ptr = msg->payload;
print_frame1(payload_ptr);
cJSON_Delete(payload_ptr);
MQTTClient_freeMessage(&msg);
MQTTClient_free(topicName);
return 1;
}
But the result is exactly the same : printing msg->payload
on the publisher side works fine so it looks like the message is correctly created, but I get a segmentation fault (core dumped)
at the first print_frame1(msg->payload)
on the receiving side. The seg fault however appears to be for a different reason than previously.
Here is what I get when I run gdb :
Program terminated with signal 11, Segmentation fault.
#0 __strlen_sse2 () at ../sysdeps/x86_64/strlen.S:32
32 movdqu (%rdi), %xmm1
I thought JSON would solve my problem, but either I am using it wrong or there is something deeper going on. I think maybe the problem could come from sizeof(payload)
in the message creation, but at this point I am very confused.
I just looked into cJSON yesterday, so I will keep investigating in case I am using it wrong, but any help would be appreciated.