How to make D-Bus server side call as asynchronous?

Viewed 3015

For my project , I am using DBUS as IPC to interact between QT application ( Client Side ) and my service daemon (Server-Side - GIO / GDBUS ). At client side , methods are invoked asynchronously using QDBusPendingCallWatcher.

However at server side , how to make method call as async ? . As per my understanding , "g_dbus_method_invocation_return_value" will return response with output parameters making method invocation as sync.

One way I can think of is to return intermediate response using g_dbus_method_invocation_return_value and then once final response is received emit the final response as signal.

Sample Code :-

//Method invocation      

static void handle_method_call(GDBusConnection *conn,
                               const gchar *sender,
                               const gchar *object_path,
                               const gchar *interface_name,
                               const gchar *method_name,
                               GVariant *parameters,
                               GDBusMethodInvocation *invocation,
                               gpointer user_data)

{

    if (!g_strcmp0(method_name, "Scan")) {
        guint8 radiotype = 0;
        guint8temp_resp = 0 ;
        g_variant_get(parameters, "(y)", radiotype);
        // Async Function Call and takes very 
        // long time to return final response as needs to scan whole radio band 
        temp_resp = RadioScan(radiotype); 

        g_dbus_method_invocation_return_value(invocation, g_variant_new("(y", temp_resp)); // return intermediate response to client  and when final response is received then  emit the signal
        g_free(response);
    }
}
// Final scan response callback function
static gboolean on_scanfinalresponse_cb (gpointer user_data)
{

    GDBusConnection *connection = G_DBUS_CONNECTION (user_data);

    GVariantBuilder *builder;

    GVariantBuilder *invalidated_builder;

    GError *error;
    g_dbus_connection_emit_signal (connection,
                                   NULL,
                                   "/org/example/test",
                                   "org.example.test",
                                   "ScanFinalResponse",
                                   g_variant_new ("(s)",
                                                  builder),
                                   &error);
    g_assert_no_error (error);
    return TRUE;
}

Please let me know is it right approach or is there any better way to achieve async call for the above case ?

1 Answers
Related