Skip to content

Instantly share code, notes, and snippets.

@kapil1024
Created June 12, 2021 06:32
Show Gist options
  • Save kapil1024/67cd6314d515b978aa9e1f92802a40af to your computer and use it in GitHub Desktop.
Save kapil1024/67cd6314d515b978aa9e1f92802a40af to your computer and use it in GitHub Desktop.
sdbus library: dbus client-server using socket pair
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <systemd/sd-bus.h>
int fds[2];
#define INT_TO_PTR(integer) ((void*) (long) ((int)integer))
#define PTR_TO_INT(ptr) ((int) (long) (ptr))
static int method_multiply(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
int64_t x, y;
int r;
/* Read the parameters */
r = sd_bus_message_read(m, "xx", &x, &y);
if (r < 0) {
fprintf(stderr, "Failed to parse parameters: %s\n", strerror(-r));
return r;
}
/* Reply with the response */
return sd_bus_reply_method_return(m, "x", x * y);
}
static int method_divide(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
int64_t x, y;
int r;
/* Read the parameters */
r = sd_bus_message_read(m, "xx", &x, &y);
if (r < 0) {
fprintf(stderr, "Failed to parse parameters: %s\n", strerror(-r));
return r;
}
/* Return an error on division by zero */
if (y == 0) {
sd_bus_error_set_const(ret_error, "net.poettering.DivisionByZero", "Sorry, can't allow division by zero.");
return -EINVAL;
}
return sd_bus_reply_method_return(m, "x", x / y);
}
/* The vtable of our little object, implements the net.poettering.Calculator interface */
static const sd_bus_vtable calculator_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("Multiply", "xx", "x", method_multiply, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Divide", "xx", "x", method_divide, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END
};
void *server(void *p) {
sd_bus_slot *slot = NULL;
sd_bus *bus = NULL;
int r;
sd_id128_t id;
r = sd_id128_randomize(&id);
if (r < 0) {
fprintf(stderr, "Failed to get new bus id: %s\n", strerror(-r));
goto finish;
}
r = sd_bus_new(&bus);
if (r < 0) {
fprintf(stderr, "Failed to create new bus: %s\n", strerror(-r));
goto finish;
}
r = sd_bus_set_fd(bus, fds[0], fds[0]);
if (r < 0) {
fprintf(stderr, "Failed to set bus fd: %s\n", strerror(-r));
goto finish;
}
r = sd_bus_set_server(bus, 1, id);
if (r < 0) {
fprintf(stderr, "Failed to set bus server id: %s\n", strerror(-r));
goto finish;
}
/* Install the object */
r = sd_bus_add_object_vtable(bus,
&slot,
"/net/poettering/Calculator", /* object path */
"net.poettering.Calculator", /* interface name */
calculator_vtable,
NULL);
if (r < 0) {
fprintf(stderr, "Failed to issue method call: %s\n", strerror(-r));
goto finish;
}
/* Take a well-known service name so that clients can find us */
r = sd_bus_request_name(bus, "net.poettering.Calculator", 0);
if (r < 0) {
fprintf(stderr, "Failed to acquire service name: %s\n", strerror(-r));
goto finish;
}
r = sd_bus_start(bus);
if (r < 0) {
fprintf(stderr, "Failed to start bus: %s\n", strerror(-r));
goto finish;
}
for (;;) {
/* Process requests */
r = sd_bus_process(bus, NULL);
if (r < 0) {
fprintf(stderr, "Failed to process bus: %s\n", strerror(-r));
goto finish;
}
if (r > 0) /* we processed a request, try to process another one, right-away */
continue;
/* Wait for the next request to process */
r = sd_bus_wait(bus, (uint64_t) -1);
if (r < 0) {
fprintf(stderr, "Failed to wait on bus: %s\n", strerror(-r));
goto finish;
}
}
finish:
sd_bus_slot_unref(slot);
sd_bus_flush(bus);
sd_bus_unref(bus);
return INT_TO_PTR(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
int client () {
sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus_message *m = NULL;
sd_bus *bus = NULL;
int64_t x, y, z;
int r;
r = sd_bus_new(&bus);
if (r < 0) {
fprintf(stderr, "Failed to create new bus: %s\n", strerror(-r));
goto finish;
}
r = sd_bus_set_fd(bus, fds[1], fds[1]);
if (r < 0) {
fprintf(stderr, "Failed to set bus fds: %s\n", strerror(-r));
goto finish;
}
r = sd_bus_start(bus);
if (r < 0) {
fprintf(stderr, "Failed to start the bus: %s\n", strerror(-r));
goto finish;
}
/* Issue the method call and store the respons message in m */
x = 99;
y = 17;
r = sd_bus_call_method(bus,
"net.poettering.Calculator", /* service to contact */
"/net/poettering/Calculator", /* object path */
"net.poettering.Calculator", /* interface name */
"Divide", /* method name */
&error, /* object to return error in */
&m, /* return message on success */
"xx", /* input signature */
x, /* first argument */
y); /* second argument */
if (r < 0) {
fprintf(stderr, "Failed to issue method call: %s\n", error.message);
goto finish;
}
/* Parse the response message */
r = sd_bus_message_read(m, "x", &z);
if (r < 0) {
fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r));
goto finish;
}
printf("%ld/%ld=%ld\n", x, y, z);
finish:
sd_bus_error_free(&error);
sd_bus_message_unref(m);
sd_bus_unref(bus);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
int main(int argc, char *argv[]) {
pthread_t s;
void *p;
int r, q;
r = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
if (r < 0) {
fprintf(stderr, "Failed to create socket pair: %s\n", strerror(-r));
return -r;
}
r = pthread_create(&s, NULL, server, NULL);
if (r != 0)
return -r;
r = client();
q = pthread_join(s, &p);
if (q != 0)
return -q;
if (r < 0)
return r;
if (PTR_TO_INT(p) < 0)
return PTR_TO_INT(p);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment