Created
November 25, 2021 17:10
-
-
Save DieTime/b5c63cfd3a5c8d7641c29fffb2c40064 to your computer and use it in GitHub Desktop.
DBus targeted signals
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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