Skip to content

Instantly share code, notes, and snippets.

@DieTime
Created November 25, 2021 17:10
Show Gist options
  • Save DieTime/b5c63cfd3a5c8d7641c29fffb2c40064 to your computer and use it in GitHub Desktop.
Save DieTime/b5c63cfd3a5c8d7641c29fffb2c40064 to your computer and use it in GitHub Desktop.
DBus targeted signals
#include <stdio.h>
#include <glib.h>
#include "signal-test-dbus.h"
static GSList *subscribers = NULL;
static GDBusConnection *connection = NULL;
static void emit_targeted_signal(gpointer subscriber, G_GNUC_UNUSED gpointer user_data) {
g_print("Send signal to %s\n", (char *)subscriber);
g_dbus_connection_emit_signal(connection,
(char *)subscriber,
"/org/unknown/SignalTest",
"org.unknown.SignalTest",
"signal",
NULL,
NULL);
}
static gboolean schedule_emit_signal_cb(G_GNUC_UNUSED gpointer user_data)
{
g_slist_foreach(subscribers, emit_targeted_signal, NULL);
return G_SOURCE_CONTINUE;
}
static gboolean handle_call(RuOmpSignalTest *object, GDBusMethodInvocation *invocation)
{
ru_omp_signal_test_complete_call(object, invocation, TRUE);
const char *sender = g_dbus_message_get_sender(g_dbus_method_invocation_get_message(invocation));
if (g_slist_index(subscribers, sender) != -1) {
g_print("Sender %s already in subscribers\n", sender);
return TRUE;
}
subscribers = g_slist_append(subscribers, g_strdup(sender));
g_print("Sender %s now in subscribers\n", sender);
return TRUE;
}
static void on_bus_acquired(GDBusConnection *conn,
G_GNUC_UNUSED const gchar *name,
G_GNUC_UNUSED gpointer user_data)
{
g_autoptr(GError) error = NULL;
RuOmpSignalTest *interface = ru_omp_signal_test_skeleton_new();
g_signal_connect(interface, "handle-call", G_CALLBACK(handle_call), NULL);
if (!g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(interface),
conn,
"/org/unknown/SignalTest",
&error))
{
g_warning("An error has occurred on bus acquired: %s", error->message);
}
connection = conn;
}
static void on_signal_received(G_GNUC_UNUSED GDBusConnection *connection,
G_GNUC_UNUSED const gchar *sender_name,
G_GNUC_UNUSED const gchar *object_path,
G_GNUC_UNUSED const gchar *interface_name,
G_GNUC_UNUSED const gchar *signal_name,
G_GNUC_UNUSED GVariant *parameters,
G_GNUC_UNUSED gpointer user_data)
{
g_print("Signal received\n");
}
int main(int argc, char *argv[])
{
if (argc == 2 && !g_strcmp0("-d", argv[1]))
{
GMainLoop *loop = g_main_loop_new(NULL, FALSE);
guint id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
"org.unknown.SignalTest",
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | G_BUS_NAME_OWNER_FLAGS_REPLACE,
on_bus_acquired,
NULL,
NULL,
loop,
NULL);
if (id == 0)
{
g_warning("couldn't initialize dbus main loop and acquire DBus name");
return EXIT_FAILURE;
}
g_print("Start sending signals every 5 seconds\n");
g_timeout_add(5000, schedule_emit_signal_cb, NULL);
g_main_loop_run(loop);
g_bus_unown_name(id);
g_main_loop_unref(loop);
}
else
{
g_autoptr(GError) error = NULL;
g_autoptr(GDBusConnection) connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
if (connection == NULL)
{
g_warning("couldn't connect to system bus when checking integrity");
return 1;
}
if (argc == 2 && !g_strcmp0("subscribe", argv[1]))
{
g_autoptr(GDBusMessage) msg = g_dbus_message_new_method_call("org.unknown.SignalTest",
"/org/unknown/SignalTest",
"org.unknown.SignalTest",
"call");
g_print("Send message to daemon\n");
g_autoptr(GDBusMessage) reply = g_dbus_connection_send_message_with_reply_sync(connection,
msg,
G_DBUS_SEND_MESSAGE_FLAGS_NONE,
1000,
NULL,
NULL,
&error);
if (reply == NULL)
{
g_warning("couldn't send DBus message to daemon");
return 1;
}
if (g_dbus_message_get_message_type(reply) == G_DBUS_MESSAGE_TYPE_ERROR)
{
g_dbus_message_to_gerror(reply, &error);
g_warning("error reply from daemon: %s", error->message);
return 1;
}
GVariant *body = g_dbus_message_get_body(reply);
if (body == NULL)
{
g_warning("bad reply from daemon: empty reply body");
return 1;
}
g_autoptr(GVariant) arg0 = g_variant_get_child_value(body, 0);
if (!g_variant_is_of_type(arg0, G_VARIANT_TYPE_BOOLEAN))
{
g_warning("invalid reply argument: argument not boolean");
return 1;
}
g_print("Received from \"call\" method: %d\n", g_variant_get_boolean(arg0));
}
GMainLoop *loop = g_main_loop_new(NULL, FALSE);
g_dbus_connection_signal_subscribe(connection,
"org.unknown.SignalTest",
"org.unknown.SignalTest",
"signal",
"/org/unknown/SignalTest",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
on_signal_received,
NULL,
NULL);
g_print("Start listening signal...\n");
g_main_loop_run(loop);
g_main_loop_unref(loop);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment