dbus c program - send(with reply) and receive using method_call - dbus

I'm new to D-Bus. I want a c program to send and receive data using the dbus_message_new_method_call function. I have tried the following programs from the link How to reply a D-Bus message but I'm getting error in the server.c side like "the name client.signal.Object was not provided by any .service files"
"server.c"
/* server.c */
#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
static DBusHandlerResult
filter_func(DBusConnection *connection, DBusMessage *message, void *usr_data)
{
DBusMessage *reply;
dbus_bool_t handled = false;
char *word = NULL;
DBusError dberr;
dbus_error_init(&dberr);
dbus_message_get_args(message, &dberr, DBUS_TYPE_STRING, &word, DBUS_TYPE_INVALID);
printf("receive message: %s\n", word);
handled = true;
reply = dbus_message_new_method_return(message);
char * reply_content;
printf("\nEnter your Reply Msg : ");
scanf("%s",reply_content);
dbus_message_append_args(reply, DBUS_TYPE_STRING, &reply_content, DBUS_TYPE_INVALID);
dbus_connection_send(connection, reply, NULL);
dbus_connection_flush(connection);
dbus_message_unref(reply);
return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
}
int main(int argc, char *argv[])
{
DBusError dberr;
DBusConnection *dbconn;
dbus_error_init(&dberr);
dbconn = dbus_bus_get(DBUS_BUS_SESSION, &dberr);
if (!dbus_connection_add_filter(dbconn, filter_func, NULL, NULL))
{
return -1;
}
dbus_bus_add_match(dbconn, "type='method_call',interface='client.signal.Type'", &dberr);
while(dbus_connection_read_write_dispatch(dbconn, -1))
{
/* loop */
}
return 0;
}
here client.c
#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
static DBusHandlerResult
filter_func(DBusConnection *connection, DBusMessage *message, void *usr_data)
{
dbus_bool_t handled = false;
char *word = NULL;
DBusError dberr;
dbus_error_init(&dberr);
dbus_message_get_args(message, &dberr, DBUS_TYPE_STRING, &word, DBUS_TYPE_INVALID);
printf("receive message %s\n", word);
handled = true;
return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
}
int db_send(DBusConnection *dbconn)
{
DBusMessage *dbmsg;
char *word = (char *)malloc(sizeof(char));
int i;
dbmsg = dbus_message_new_method_call("client.signal.Object","/client/signal/Object", "client.signal.Type", "Test");
scanf("%s", word);
if (!dbus_message_append_args(dbmsg, DBUS_TYPE_STRING, &word, DBUS_TYPE_INVALID))
{
return -1;
}
if (!dbus_connection_send(dbconn, dbmsg, NULL))
{
return -1;
}
dbus_connection_flush(dbconn);
printf("send message %s\n", word);
dbus_message_unref(dbmsg);
return 0;
}
int main(int argc, char *argv[])
{
DBusError dberr;
DBusConnection *dbconn;
dbus_error_init(&dberr);
dbconn = dbus_bus_get(DBUS_BUS_SESSION, &dberr);
if (!dbus_connection_add_filter(dbconn, filter_func, NULL, NULL))
{
return -1;
}
db_send(dbconn);
while(dbus_connection_read_write_dispatch(dbconn, -1))
{
db_send(dbconn);
}
dbus_connection_unref(dbconn);
return 0;
}
Please help me to fix.

Have a look here: http://www.freedesktop.org/wiki/IntroductionToDBus/
From what it looks like you need to write a file "*.service" that describes the service.
(Quoted from the website)
# (Lines starting with hash marks are comments)
# Fixed section header (do not change):
[D-BUS Service]
Names=com.bigmoneybank.Deposits;com.bigmoneybank.Withdrawals
Exec=/usr/local/bin/bankcounter
This is what I found within 5 minutes of Googleing.

Related

I'm not able to pass a callback function with a new argument i added in c

I don't know how to pass a variable into a callback to do some stuff (print json output) inside this function.
In sample code there is no other functions i need to pass but with sqlite3 I think I have to do this in the callback, tell me if i'm doing wrong.
The callback is called in sendhosts() function in my code.
I get this error :
In function ‘sendhosts’:
sample.c:85:48: error: too few arguments to function ‘callback’
rc = sqlite3_exec(db, "SELECT * FROM hosts;", callback(req), 0, &zErrMsg);
Original code is :
#include <stdio.h>
#include <sqlite3.h>
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
int main(int argc, char **argv){
sqlite3 *db;
char *zErrMsg = 0;
int rc;
if( argc!=3 ){
fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);
return(1);
}
rc = sqlite3_open(argv[1], &db);
if( rc ){
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return(1);
}
rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg);
if( rc!=SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
sqlite3_close(db);
return 0;
}
My code is :
#include <sys/types.h> /* size_t, ssize_t */
#include <stdarg.h> /* va_list */
#include <stddef.h> /* NULL */
#include <stdint.h> /* int64_t */
#include <stdlib.h>
#include <string.h> /* memset */
#include <stdio.h>
#include <kcgi.h>
#include <kcgihtml.h>
#include <sqlite3.h>
enum page {
PAGE_HOSTS,
PAGE__MAX
};
enum key {
KEY_INTEGER,
KEY_FILE,
KEY_PAGECOUNT,
KEY_PAGESIZE,
KEY__MAX
};
struct tstrct {
struct khtmlreq req;
struct kreq *r;
};
typedef void (*disp)(struct kreq *);
static void sendhosts(struct kreq *);
static const disp disps[PAGE__MAX] = {
sendhosts, /* PAGE_SENDDATA */
};
static const struct kvalid keys[KEY__MAX] = {
{ kvalid_int, "integer" }, /* KEY_INTEGER */
{ NULL, "file" }, /* KEY_FILE */
{ kvalid_uint, "count" }, /* KEY_PAGECOUNT */
{ kvalid_uint, "size" }, /* KEY_PAGESIZE */
};
static const char *const pages[PAGE__MAX] = {
"sendhosts" /* PAGE_SENDDATA */
};
static void
resp_open(struct kreq *req, enum khttp http)
{
enum kmime mime;
if (KMIME__MAX == (mime = req->mime))
mime = KMIME_APP_OCTET_STREAM;
khttp_head(req, kresps[KRESP_STATUS],
"%s", khttps[http]);
khttp_head(req, kresps[KRESP_CONTENT_TYPE],
"%s", kmimetypes[mime]);
khttp_body(req);
}
static int callback(struct kreq *req, int argc, char **argv, char **azColName){
char *page;
struct khtmlreq r;
resp_open(req, KHTTP_200);
khtml_open(&r, req, 0);
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
struct khtmlreq r;
khtml_puts(&r, "OK");
}
khtml_close(&r);
free(page);
}
static void
sendhosts(struct kreq *req)
{
sqlite3 *db;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("/var/www/MaSSH/databases/massh.db", &db);
if(rc){
sqlite3_close(db);
}
rc = sqlite3_exec(db, "SELECT * FROM hosts;", callback(req), 0, &zErrMsg);
if(rc!= SQLITE_OK){
sqlite3_free(zErrMsg);
}
sqlite3_close(db);
}
int
main(void)
{
struct kreq r;
enum kcgi_err er;
/* Set up our main HTTP context. */
er = khttp_parse(&r, keys, KEY__MAX,
pages, PAGE__MAX, PAGE_HOSTS);
if (KCGI_OK != er)
return(EXIT_FAILURE);
/*
* Accept only GET, POST, and OPTIONS.
* Restrict to text/html and a valid page.
* If all of our parameters are valid, use a dispatch array to
* send us to the page handlers.
*/
if (KMETHOD_OPTIONS == r.method) {
khttp_head(&r, kresps[KRESP_ALLOW],
"OPTIONS GET POST");
resp_open(&r, KHTTP_200);
} else if (KMETHOD_GET != r.method &&
KMETHOD_POST != r.method) {
resp_open(&r, KHTTP_405);
} else if (PAGE__MAX == r.page ||
KMIME_TEXT_HTML != r.mime) {
resp_open(&r, KHTTP_404);
} else
(*disps[r.page])(&r);
khttp_free(&r);
return(EXIT_SUCCESS);
}
Your callback's signature
static int callback(struct kreq *req, int argc, char **argv, char **azColName)
is wrong. It should be
static int callback(void *ptr, int argc, char **argv, char **azColName) {
struct kreq *req = (struct kreq *)ptr;
The callback's signature should exactly match the function pointer's format, which, for sqlite3_exec, is int (*callback)(void *, int, char **, char **).
And this
rc = sqlite3_exec(db, "SELECT * FROM hosts;", callback(req), 0, &zErrMsg);
should be
rc = sqlite3_exec(db, "SELECT * FROM hosts;", callback, req, &zErrMsg);
callback(req) calls callback, which is not what you want; you're trying to pass a function pointer to a function, which is done with just the function's name.

C program not reading keyboard input

EDIT: the problem is that scanf (and other function I tried here) doesn't wait for the input, the program doesn't pause.
Using Ubuntu 18 on Virtual Box on Mac
I am writing a server/client using POSIX. I am not able to read keyboard input in client.c
char action_type[1];
printf("Chose action: T to request time, S to shut down\n");
scanf(" %c",action_type);
printf("%s", action_type);
if I put the same code as the first thing in main.c it works fine.
full code for server / client and commons is:
server
#include <stdio.h>
#include "mqueue.h"
#include "commons.h"
#include "errno.h"
#include "stdlib.h"
#include <string.h>
#include <time.h>
int status_closing = 0;
void send_time(char* clients_pid);
void send_activation(char* clients_pid);
//VARIABLES related to SERVERS QUEUE
mqd_t server; // server
struct mq_attr servers_attributes; // server creation attributes
struct mq_attr receiving_attributes; // server receiving attributes
// set up attributes
void set_servers_attributes(){
// set up server's attributes
servers_attributes.mq_maxmsg = QUEUE_SIZE;
servers_attributes.mq_msgsize = MESSAGE_SIZE;
printf("attributes set \n");
};
// open server
void open_servers_queue() {
server = mq_open (servers_path,
O_CREAT | O_RDWR | O_EXCL ,
0666, &servers_attributes);
if (server == -1) {
printf("failed to open server's queue\n");
printf(errno);
exit(-1);
} else {
printf("opened servers queue as: %d\n",server);
}
};
// check attributes
void check_attributes(){
if ((mq_getattr(server,&receiving_attributes)) == -1) {
printf("cannot read server's queue\n exit \n");
exit(-1);
}
};
void close_and_unlink_queue(){
printf("At exit closing and unlinking queue\n");
mq_close(server);
mq_unlink(servers_path);
};
int check_for_messages_in_the_queue(){
//printf("checking for messages\n");
int messages_in_queue;
messages_in_queue = receiving_attributes.mq_curmsgs;
//printf("there are %d message in the servers queue\n",messages_in_queue);
// printf("message in the queue!\n");
return messages_in_queue;
};
char* receive_message(){
char *receiving_buffer = malloc(sizeof(char)*MESSAGE_SIZE);
if ((mq_receive(server,receiving_buffer,MESSAGE_SIZE,NULL))>0){
return receiving_buffer;
}
else {
printf("Server failed to receive message");
mq_close(server);
mq_unlink(servers_path);
exit(-1);
}
};
void respond(char *message_type, char* clients_pid) {
printf("responding\n");
char* type_one = "1";
char* type_two = "2";
char *type_three ="3";
if (strcmp(message_type, type_one) == 0) {
printf("TYPE 1\n");
send_activation(clients_pid);
}
if (strcmp(message_type, type_two) == 0) {
printf("TYPE 2\n");
send_time(clients_pid);
}
if (strcmp(message_type, type_three) == 0) {
printf("type 3 - SHUTDOWN INITIATED\n");
}
}
void send_time(char* clients_pid) {
time_t mytime = time(NULL);
char *time_str = ctime(&mytime);
time_str[strlen(time_str)-1] = '\0';
char *clientpath[20];
int clients_pid_int = atoi(clients_pid);
sprintf(clientpath,"/%d",clients_pid_int);
printf("clients path: %s\n",clientpath);
mqd_t client;
client = mq_open(clientpath,O_RDWR , 0666, &servers_attributes);
if (client == -1) {
printf("failes opening client's queue \n");
exit(-1);
} else {
printf("connected to client's queue: %d\n",client);
}
};
void send_activation(char* clients_pid) {
char *clientpath[20];
int clients_pid_int = atoi(clients_pid);
sprintf(clientpath,"/%d",clients_pid_int);
printf("clients path: %s\n",clientpath);
mqd_t client;
client = mq_open(clientpath,O_RDWR , 0666, &servers_attributes);
if (client == -1) {
printf("failes opening client's queue \n");
exit(-1);
} else {
printf("connected to client's queue: %d\n",client);
char* activation = malloc(sizeof(char)*MESSAGE_SIZE);
char* activation_literal = "activation";
sprintf(activation,"%s",activation_literal);
int message_sent = mq_send(client,activation,MESSAGE_SIZE,0);
printf("message sent with: %d",message_sent);
}
};
int main() {
// clean remainings of previous trials
mq_close(server);
mq_unlink(servers_path);
// define atexit behaviour
atexit(close_and_unlink_queue);
//set servers attributes:
set_servers_attributes();
// open server's queue
open_servers_queue();
// receiving messages in the loop
int condition = 1;
while (1) {
check_attributes();
if (check_for_messages_in_the_queue() > 0) {
char *received_message = receive_message();
char *tok_one = strtok(received_message," ");
char *tok_two = strtok(NULL, " ");
//int clients_pid = atoi(tok_two);
respond(tok_one,tok_two);
} else if ((check_for_messages_in_the_queue() ==0) && (status_closing == 1)) {
printf("Server's queue is empty - work finished. closing down\n");
exit(0);
}
}
printf("Hello, World!\n");
return 0;
}
client
#include <stdio.h>
#include <mqueue.h>
#include <unistd.h>
#include "commons.h"
#include <stdlib.h>
#include <errno.h>
#include <string.h>
mqd_t client;
mqd_t server;
char clientpath[20];
char* sending_buffer[MESSAGE_SIZE];
struct mq_attr clients_attributes;
struct mq_attr receiving_attributes;
void connect_to_server(){
server = mq_open(servers_path,O_WRONLY);
if(server == -1) {
printf("connection to server failed\n");
} else {
printf("connected to server with id: %d \n",server);
}
};
void set_clients_attributes(){
// deal with attributes
clients_attributes.mq_maxmsg = QUEUE_SIZE;
clients_attributes.mq_msgsize = MESSAGE_SIZE;
};
void create_clients_queue(){
// create clients path
pid_t client_pid = getpid();
sprintf(clientpath, "/%d", client_pid);
// open clients queue
client = mq_open(clientpath,O_RDONLY | O_CREAT | O_EXCL, 0666, &clients_attributes);
// printf(errno);
if (client == -1) {
printf("failes opening client's queue \n");
exit(-1);
} else {
printf("connected to client's queue: %d\n",client);
}
};
void register_at_server(){
message message;
message.mtype = 1;
int client_pid = getpid();
message.sender = client_pid;
char separator = ' ';
snprintf(sending_buffer,MESSAGE_SIZE,"%ld%c%d",message.mtype,separator,message.sender);
if ((mq_send(server,sending_buffer, MESSAGE_SIZE,0)) == -1) {
printf("failed to send registration request\n");
exit(-1);
}
else {
printf("%s",sending_buffer);
printf("sent registration request\n");
}
};
void close_and_unlink_queue(){
printf("At exit closing and unlinking queue\n");
mq_close(client);
mq_unlink(clientpath);
};
void check_attributes(){
if ((mq_getattr(client,&receiving_attributes)) == -1) {
printf("cannot read own's queue\n exit \n");
exit(-1);
}
};
int check_for_messages_in_the_queue(){
//printf("checking for messages\n");
int messages_in_queue;
messages_in_queue = receiving_attributes.mq_curmsgs;
//printf("there are %d message in the servers queue\n",messages_in_queue);
// printf("message in the queue!\n");
return messages_in_queue;
};
char* receive_message(){
char *receiving_buffer = malloc(sizeof(char)*MESSAGE_SIZE);
if ((mq_receive(client,receiving_buffer,MESSAGE_SIZE,NULL))>0){
return receiving_buffer;
}
else {
printf("Server failed to receive message");
mq_close(client);
mq_unlink(clientpath);
exit(-1);
}
};
void choose_action(){
char action_type[1];
printf("Chose action: T to request time, S to shut down\n");
scanf(" %c",action_type);
printf("%s", action_type);
};
int main() {
mq_close(client);
mq_unlink(clientpath);
connect_to_server();
set_clients_attributes();
create_clients_queue();
register_at_server();
int condition = 1;
int client_active = 0;
while (condition) {
check_attributes();
if (check_for_messages_in_the_queue() > 0) {
char *received_message = receive_message();
if ((strcmp(received_message, "activation")) == 0) {
client_active = 1;
condition = 0;
free(received_message);
}
}
}
char action_type[1];
printf("Chose action: T to request time, S to shut down\n");
scanf(" %c",action_type);
printf("%s", action_type);
printf("Hello, World!\n");
return 0;
}
commons
#ifndef SERVER_COMMONS_H
#define SERVER_COMMONS_H
#include <signal.h>
// define values of server queue attributes
//define message struct
typedef struct messgae {
char content[4096];
pid_t sender;
long mtype;
} message;
#define QUEUE_SIZE 10
#define MESSAGE_SIZE sizeof(message)
// define servers path
const char servers_path[] = "/server";
#endif //SERVER_COMMONS_H
``
this happens because the buffer is not empty and this function read from it.
to empty buffer just try this code:
while( getchar() != '\n');
it will empty the buffer and after it the functions will wait for input.
printf( "Enter a value :");
c = getchar( );
or
#include <stdio.h>
int main( ) {
char str[100];
int i;
printf( "Enter a value :");
scanf("%s %d", str, &i);
printf( "\nYou entered: %s %d ", str, i);
return 0;
}

Why is this message sent using paho.mqtt.c causing segmentation fault?

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, then before asking this question, I also tried using JSON to create my specific message type. I installed cJSON (from here).
Here is my whole code using cJSON :
pubframe.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#include "../tools.c"
#include <cjson/cJSON.h>
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "MY_PUB"
#define TOPIC "MQTT/Test"
int main(int argc, char* argv[])
{
frame1 test = {42,"test"};
cJSON* frm = NULL;
frm = cJSON_CreateObject();
cJSON_AddNumberToObject(frm,"entier",test.E);
cJSON_AddStringToObject(frm,"string",test.S);
print_frame1(frm);
int i = cJSON_GetArraySize(frm);
printf("number of items in frame : %d\n",i);
cJSON* entier = NULL;
entier = cJSON_GetObjectItem(frm,"entier");
char* pt = cJSON_Print(entier);
printf("entier : %s\n",pt);
cJSON* str = NULL;
str = cJSON_GetObjectItem(frm,"string");
char* st = cJSON_Print(str);
printf("string : %s\n",st);
printf("size of message : %d\n",sizeof(cJSON));
MQTTClient publisher;
MQTTClient_connectOptions connexion = MQTTClient_connectOptions_initializer;
MQTTClient_message msg = msg_creation(frm,sizeof(cJSON),0,0);
MQTTClient_deliveryToken token;
int rc;
MQTTClient_create(&publisher, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
connexion.cleansession = 1;
MQTTClient_setCallbacks(publisher, NULL, connlost, frame_json_arrvd, NULL);
if ((rc = MQTTClient_connect(publisher,&connexion)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
}
MQTTClient_publishMessage(publisher, TOPIC,&msg,NULL);
printf("Message sent!\n");
cJSON_Delete(frm);
MQTTClient_disconnect(publisher,10000);
MQTTClient_destroy(&publisher);
return rc;
}
subframe.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#include "../tools.c"
#include <cjson/cJSON.h>
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "ClientID"
#define TOPIC "MQTT/Test"
#define QOS 0
#define TIMEOUT 10000L
int main(int argc, char* argv[])
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
int rc;
int ch;
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
MQTTClient_setCallbacks(client, NULL, connlost, frame_json_arrvd, NULL);
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
"Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
MQTTClient_subscribe(client, TOPIC, QOS);
do
{
ch = getchar();
} while(ch!='Q' && ch != 'q');
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return rc;
}
tools.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <cjson/cJSON.h>
#include "MQTTClient.h"
int compteur;
// message frames
typedef struct frame1
{
int E;
char* S;
} frame1;
void print_frame1bis(frame1* F)
{
printf(" %s\n",F->S);
printf(" %d\n",F->E);
}
void print_frame1(cJSON* frame1)
{
char * str = cJSON_Print(frame1);
printf("%s\n",str);
}
int frame_json_arrvd(void* context, char* topicName, int topicLen, MQTTClient_message* msg)
{
cJSON* payload_ptr = NULL;
printf("size of message : %d\n",sizeof(msg->payload));
int j = cJSON_GetArraySize(msg->payload);
printf("ok\n");
printf("number of items in frame : %d\n",j);
payload_ptr = cJSON_CreateObject();
payload_ptr = msg->payload;
int i = cJSON_GetArraySize(payload_ptr);
printf("number of items in frame : %d\n",i);
print_frame1(payload_ptr);
cJSON_Delete(payload_ptr);
MQTTClient_freeMessage(&msg);
MQTTClient_free(topicName);
return 1;
}
// in case connexion is lost
void connlost(void *context, char *cause)
{
printf("\nConnection lost\n");
printf(" cause: %s\n", cause);
}
// create message
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;
}
The outpus from the subscriber is
Subscribing to topic MQTT/Test
for client ClientID using QoS0
Press Q<Enter> to quit
size of message : 8
Segmentation fault (core dumped)
So it seems the message is not correctly received as the subscriber crashes as soon as it tries to get the number of items.
This is what I get when I run gdb, not sure if it helps.
Program terminated with signal 11, Segmentation fault.
#0 0x00007f4e49a8b63e in cJSON_GetArraySize () from /usr/lib64/libcjson.so.1
(gdb) bt
#0 0x00007f4e49a8b63e in cJSON_GetArraySize () from /usr/lib64/libcjson.so.1
#1 0x00000000004010c9 in frame_json_arrvd (context=0x0,
topicName=0x7f4e440009e4 "MQTT/Test", topicLen=0, msg=0x7f4e44000bb4)
at ../tools.c:110
#2 0x00007f4e49c962a5 in MQTTClient_run (n=<value optimized out>)
at src/MQTTClient.c:604
#3 0x000000378b807aa1 in start_thread (arg=0x7f4e49a83700) at pthread_create.c:301
#4 0x000000378b4e8bcd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:115
The output from the publisher is
{
"entier": 42,
"string": "test"
}
number of items in frame : 2
entier : 42
string : "test"
size of message : 64
Message sent!
So it looks like the message is correctly created.
I just looked into cJSON recently, so I will keep investigating in case I am using it wrong, but any help would be appreciated.
I tried to narrow it down as suggested in the comments, but I don't see what I can do, seeing as it crashes as soon as it tries to access to the payload of the message.
Please keep in mind I am only a student with no more than a year of experience in computer science. Also, english is not my native language, I hope I am explaining myself clearly enough.
Problem solved (kinda)
I just send the whole message frame as a string and parse it in the msgarrvd function :
pubframe.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#include "../tools.c"
#include <cjson/cJSON.h>
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "MY_PUB"
#define TOPIC "MQTT/Test"
volatile MQTTClient_deliveryToken deliveredtoken;
void delivered(void *context, MQTTClient_deliveryToken dt)
{
printf("Message with token value %d delivery confirmed\n", dt);
deliveredtoken = dt;
}
int main(int argc, char* argv[])
{
char* test = "{\"string\" : \"whatever\", \"entier\" : 42}";
MQTTClient publisher;
MQTTClient_connectOptions connexion = MQTTClient_connectOptions_initializer;
MQTTClient_message msg = msg_creation(test,strlen(test),0,0);
int rc;
MQTTClient_create(&publisher, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
connexion.cleansession = 1;
MQTTClient_setCallbacks(publisher, NULL, connlost, frame_test_arrvd, NULL);
if ((rc = MQTTClient_connect(publisher,&connexion)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
}
MQTTClient_publishMessage(publisher, TOPIC,&msg,&token);
printf("Message sent!\n");
cJSON_Delete(frm);
MQTTClient_disconnect(publisher,10000);
MQTTClient_destroy(&publisher);
return rc;
}
tools.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <cjson/cJSON.h>
#include "MQTTClient.h"
// message frames
void print_frame1(cJSON* frame1)
{
char * str = cJSON_Print(frame1);
printf("%s\n",str);
}
int frame_test_arrvd(void* context, char* topicName, int topicLen, MQTTClient_message* msg)
{
printf("message original : %s\n",msg->payload);
cJSON* payload_ptr = cJSON_Parse(msg->payload);
print_frame1(payload_ptr);
int i = cJSON_GetArraySize(payload_ptr);
printf("number of items in frame : %d\n",i);
cJSON* entier = NULL;
entier = cJSON_GetObjectItem(payload_ptr,"entier");
char* pt = cJSON_Print(entier);
printf("entier : %s\n",pt);
cJSON* str = NULL;
str = cJSON_GetObjectItem(payload_ptr,"string");
char* st = cJSON_Print(str);
printf("string : %s\n",st);
cJSON_Delete(payload_ptr);
MQTTClient_freeMessage(&msg);
MQTTClient_free(topicName);
return 1;
}
// in case connexion is lost
void connlost(void *context, char *cause)
{
printf("\nConnection lost\n");
printf(" cause: %s\n", cause);
}
// create message
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;
}
subframe.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MQTTClient.h"
#include "../tools.c"
#include <cjson/cJSON.h>
#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "ClientID"
#define TOPIC "MQTT/Test"
#define QOS 0
#define TIMEOUT 10000L
int main(int argc, char* argv[])
{
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
int rc;
int ch;
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
MQTTClient_setCallbacks(client, NULL, connlost, frame_test_arrvd, NULL);
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
"Press Q<Enter> to quit\n\n", TOPIC, CLIENTID, QOS);
MQTTClient_subscribe(client, TOPIC, QOS);
do
{
ch = getchar();
} while(ch!='Q' && ch != 'q');
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return rc;
}
It is not ideal as I still would like to create specific types of message, and I haven't found out what was causing the segmentation fault, but it works perfectly this way.
UPDATE
I found a way to create specific types of message and still send them as string to parse them in the msgarrvd function, I just created a function cJSON_ToString to convert a cJSON* object to a string, so that I can create a cJOSN from any struct I want and then convert it to a string to send it.

Segmentation fault error in C program using MQPUT

I have a program below
#include <stdio.h>
#include <cmqc.h>
#include <cmqxc.h>
#include "dte_mq.h"
#include <string.h>
#include <stdlib.h>
typedef struct tagDTE_QUEUE_DESCRIPTOR
{
MQHOBJ handle;
int IsSyncpointControled;
} DTE_QUEUE_DESCRIPTOR, *PDTE_QUEUE_DESCRIPTOR;
static MQHCONN sHConn = 0;
static MQLONG sCompCode = MQCC_OK;
static MQLONG sReason = MQRC_NONE;
static int sNumOpenQueues = 0;
static PDTE_QUEUE_DESCRIPTOR sQueues = NULL;
MQLONG OpenCode;
MQOD od = {MQOD_DEFAULT}; /* Object Descriptor */
MQMD md = {MQMD_DEFAULT};
MQPMO pmo = {MQPMO_DEFAULT};
MQLONG O_options;
MQLONG C_options;
MQGMO gmo = {MQGMO_DEFAULT};
/* MQCONNX options */
MQCNO Connect_options = {MQCNO_DEFAULT};
/* Client connection channel */
MQCD ClientConn = {MQCD_CLIENT_CONN_DEFAULT};
DTE_MQ_RESULT dteMqSend(int qd, void *buf, int len)
{
printf("oleg\n");
/* memcpy(md.Format, MQFMT_STRING, MQ_FORMAT_LENGTH); */
md.MsgType = MQMT_DATAGRAM;
printf("oleg1\n");
memcpy(md.MsgId, MQMI_NONE, sizeof(md.MsgId));
printf("oleg2\n");
memcpy(md.CorrelId, MQCI_NONE, sizeof(md.CorrelId));
printf("oleg3\n");
memcpy(md.Format, MQFMT_STRING, (size_t)MQ_FORMAT_LENGTH);
printf("oleg4\n");
if(sQueues[qd].IsSyncpointControled)
pmo.Options |= MQPMO_SYNCPOINT;
printf("oleg5\n");
MQPUT(sHConn, sQueues[qd].handle, &md, &pmo, len, buf, &sCompCode, &sReason);
printf("MQput CC=%ld RC=%ld\n", sCompCode, sReason);
if (sCompCode != MQCC_OK) return DTE_MQR_FAILED;
return DTE_MQR_OK;
}
I put print statement and found out that after printf("oleg4\n";) I get error
Segmentation fault
Could you please help me top debug the program? Do I have to use malloc for the structure? It is written in C and using MQPUT
Below is a program, where above function is called
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cmqc.h> /* includes for MQI */
#include <cmqxc.h>
int main(int argc, char **argv)
{
MQLONG messlen; /* message length received */
char QMgrName[MQ_Q_MGR_NAME_LENGTH+1];
char QName[MQ_Q_NAME_LENGTH+1];
char channelName[MQ_CHANNEL_NAME_LENGTH+1];
char hostname[1024];
char port[4];
MQLONG buflen;
MQBYTE TmpBuf[65536] = "This is a simple test message.";
int msgsToGet;
int msgsGot;
int dteretinit;
int dteretdeinit;
int dteretopen;
int dteretclose;
int qd;
int dteretput;
if (argc != 6)
{
printf("Usage: NewMQTest QMgrName ChlName hostname port QName\n");
exit(-1);
}
strncpy(QMgrName, argv[1], MQ_Q_MGR_NAME_LENGTH);
QMgrName[MQ_Q_MGR_NAME_LENGTH] = '\0';
strncpy(channelName, argv[2], MQ_CHANNEL_NAME_LENGTH);
channelName[MQ_CHANNEL_NAME_LENGTH] = '\0';
strncpy(hostname, argv[3], 1023);
hostname[1023] = '\0';
strncpy(port,argv[4],4);
strncpy(QName, argv[5], MQ_Q_NAME_LENGTH);
QName[MQ_Q_NAME_LENGTH] = '\0';
dteretinit = dteMqInit(QMgrName,hostname,channelName);
printf("Return code from dteMqInit = %d\n",dteretinit);
qd = -1;
dteretopen = dteMqOpen(QName, qd);
printf ("Return code from dteMqOpen = %d\n",dteretopen);
if (dteretopen == 0 )
{
buflen = strlen(TmpBuf);
TmpBuf[buflen + 1] = '\0';
dteretput = dteMqSend(qd,*TmpBuf,buflen);
printf("return mqput %d\n",dteretput);
}
dteretclose = dteMqClose(qd);
printf("Return code from dteMqClose = %d\n",dteretclose);
dteretdeinit = dteMqDeinit();
printf("Return code from dteMqDeinit = %d\n",dteretdeinit);
}
I analyzed my program and check MQ. SSL didn't let me connect to MQ, that is why I couldn't change qd. The program is very old, and when failed, return value was set up as 0, 1 is success. I never did it like that. 0 is always success.
Thanks
This is some bad code.
typedef struct tagDTE_QUEUE_DESCRIPTOR
{
MQHOBJ handle;
int IsSyncpointControled;
} DTE_QUEUE_DESCRIPTOR, *PDTE_QUEUE_DESCRIPTOR;
static PDTE_QUEUE_DESCRIPTOR sQueues = NULL;
if(sQueues[qd].IsSyncpointControled)
In the code that you have posted, 'sQueues' is never set, so that is why it is throwing segmentation fault on the 'if' statement. And if 'qd' is really '-1' as per your comment, then I have to wonder what in the world you are doing.
dteretinit = dteMqInit(QMgrName,hostname,channelName);
How come you don't pass the port number into the dteMqInit subroutine?

Char array corrupted after passing through ONC RPC

when calling a ONC-RPC-function that returns a char array I get (apparently) uninitialized memory on the first call. Subsequent calls give me the correct result.
This example showcases the issue:
ftp.x:
const BLOCKSIZE = 1024;
struct block {
char arr<BLOCKSIZE>;
};
program FILE_GET_BLOCK_PROG {
version FILE_GET_BLOCK_VERS {
block FILE_GET_BLOCK() = 1;
} = 1;
} = 0x42424243;
ftp_client.c:
#include "ftp.h"
#include <errno.h>
#include <string.h>
size_t
file_get_block_prog_1(char *host, char *buf)
{
CLIENT *clnt;
block *result_1;
#ifndef DEBUG
clnt = clnt_create (host, FILE_GET_BLOCK_PROG, FILE_GET_BLOCK_VERS, "udp");
if (clnt == NULL) {
clnt_pcreateerror (host);
exit (1);
}
#endif /* DEBUG */
result_1 = file_get_block_1(NULL, clnt);
if (result_1 == (block *) NULL) {
clnt_perror (clnt, "call failed");
}
#ifndef DEBUG
clnt_destroy (clnt);
#endif /* DEBUG */
memcpy(buf, result_1->arr.arr_val, result_1->arr.arr_len);
return result_1->arr.arr_len;
}
int
main (int argc, char *argv[])
{
char *host, *source_filename;
char buf[BLOCKSIZE+1];
int block_count;
size_t bytes_read;
if (argc < 2) {
printf ("usage: %s server_host\n", argv[0]);
exit (1);
}
host = argv[1];
bytes_read = file_get_block_prog_1 (host, buf);
buf[bytes_read] = '\0';
printf("%d bytes:\n%s\n", bytes_read, buf);
exit (0);
}
ftp_server.c:
#include "ftp.h"
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
block *
file_get_block_1_svc(void *argp, struct svc_req *rqstp)
{
static block result;
static int request = 1;
char buf[BLOCKSIZE+1];
size_t bytes_read;
strcpy(buf, "This is just a simple test block. There is nothing relevant in here.");
result.arr.arr_len = strlen(buf);
result.arr.arr_val = buf;
printf("Request #%d:\n%s\n", request++, buf);
return &result;
}
When running the server and calling the client twice, this is my output:
client:
$ ./ftp_client localhost
68 bytes:
$ ./ftp_client localhost
68 bytes:
This is just a simple test bock. There is nothing relevant in here.
server:
Request #1:
This is just a simple test bock. There is nothing relevant in here.
Request #2:
This is just a simple test bock. There is nothing relevant in here.
Is there any initialization I missed that I need to do before the first request? What else would cause this behavior?

Resources