static void la_handler_service_handle_register_finish (GObject *object, GAsyncResult *res, gpointer user_data) { GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (user_data); LAHandlerService *service; NSMConsumer *nsm_consumer = NSM_CONSUMER (object); GError *error = NULL; gint error_code; g_return_if_fail (IS_NSM_CONSUMER (nsm_consumer)); g_return_if_fail (G_IS_ASYNC_RESULT (res)); g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); /* finish registering the shutdown client */ nsm_consumer_call_register_shutdown_client_finish (nsm_consumer, &error_code, res, &error); if (error != NULL) { DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING ("Failed to register a shutdown consumer:"), DLT_STRING (error->message)); g_error_free (error); } /* retrieve the LAHandlerService from the invocation object */ service = g_object_get_data (G_OBJECT (invocation), "la-handler-service"); /* notify the caller that we have handled the registration request */ la_handler_complete_register (service->interface, invocation); }
/** * g_dbus_method_invocation_take_error: (skip) * @invocation: (transfer full): A #GDBusMethodInvocation. * @error: (transfer full): A #GError. * * Like g_dbus_method_invocation_return_gerror() but takes ownership * of @error so the caller does not need to free it. * * This method will free @invocation, you cannot use it afterwards. * * Since: 2.30 */ void g_dbus_method_invocation_take_error (GDBusMethodInvocation *invocation, GError *error) { g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); g_return_if_fail (error != NULL); g_dbus_method_invocation_return_gerror (invocation, error); g_error_free (error); }
/** * g_dbus_method_invocation_return_error_literal: * @invocation: A #GDBusMethodInvocation. * @domain: A #GQuark for the #GError error domain. * @code: The error code. * @message: The error message. * * Like g_dbus_method_invocation_return_error() but without printf()-style formatting. * * This method will free @invocation, you cannot use it afterwards. * * Since: 2.26 */ void g_dbus_method_invocation_return_error_literal (GDBusMethodInvocation *invocation, GQuark domain, gint code, const gchar *message) { GError *error; g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); g_return_if_fail (message != NULL); error = g_error_new_literal (domain, code, message); g_dbus_method_invocation_return_gerror (invocation, error); g_error_free (error); }
static void _audit_log_helper (NMAuditManager *self, GPtrArray *fields, const char *file, guint line, const char *func, const char *op, gboolean result, gpointer subject_context, const char *reason) { AuditField op_field = { }, pid_field = { }, uid_field = { }; AuditField result_field = { }, reason_field = { }; gulong pid, uid; NMAuthSubject *subject = NULL; gs_unref_object NMAuthSubject *subject_free = NULL; _audit_field_init_string (&op_field, "op", op, FALSE, BACKEND_ALL); g_ptr_array_insert (fields, 0, &op_field); if (subject_context) { if (NM_IS_AUTH_SUBJECT (subject_context)) subject = subject_context; else if (G_IS_DBUS_METHOD_INVOCATION (subject_context)) { GDBusMethodInvocation *context = subject_context; subject = subject_free = nm_auth_subject_new_unix_process_from_context (context); } else g_warn_if_reached (); } if (subject && nm_auth_subject_is_unix_process (subject)) { pid = nm_auth_subject_get_unix_process_pid (subject); uid = nm_auth_subject_get_unix_process_uid (subject); if (pid != G_MAXULONG) { _audit_field_init_uint (&pid_field, "pid", pid, BACKEND_ALL); g_ptr_array_add (fields, &pid_field); } if (uid != G_MAXULONG) { _audit_field_init_uint (&uid_field, "uid", uid, BACKEND_ALL); g_ptr_array_add (fields, &uid_field); } } _audit_field_init_string (&result_field, "result", result ? "success" : "fail", FALSE, BACKEND_ALL); g_ptr_array_add (fields, &result_field); if (reason) { _audit_field_init_string (&reason_field, "reason", reason, FALSE, BACKEND_LOG); g_ptr_array_add (fields, &reason_field); } nm_audit_log (self, fields, file, line, func, result); }
/** * g_dbus_method_invocation_return_gerror: * @invocation: A #GDBusMethodInvocation. * @error: A #GError. * * Like g_dbus_method_invocation_return_error() but takes a #GError * instead of the error domain, error code and message. * * This method will free @invocation, you cannot use it afterwards. * * Since: 2.26 */ void g_dbus_method_invocation_return_gerror (GDBusMethodInvocation *invocation, const GError *error) { gchar *dbus_error_name; g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); g_return_if_fail (error != NULL); dbus_error_name = g_dbus_error_encode_gerror (error); g_dbus_method_invocation_return_dbus_error (invocation, dbus_error_name, error->message); g_free (dbus_error_name); }
static gboolean photos_thumbnailer_handle_generate_thumbnail (PhotosThumbnailer *self, GDBusMethodInvocation *invocation, const gchar *uri, const gchar *mime_type, const gchar *orientation, gint64 original_height, gint64 original_width, GVariant *pipeline_uris_variant, const gchar *thumbnail_path, gint thumbnail_size) { g_autoptr (GCancellable) cancellable = NULL; g_auto (GStrv) pipeline_uris = NULL; g_return_val_if_fail (PHOTOS_IS_THUMBNAILER (self), FALSE); g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), FALSE); g_return_val_if_fail (uri != NULL && uri[0] != '\0', FALSE); g_return_val_if_fail (mime_type != NULL && mime_type[0] != '\0', FALSE); g_return_val_if_fail (orientation != NULL && orientation[0] != '\0', FALSE); g_return_val_if_fail (g_variant_is_of_type (pipeline_uris_variant, G_VARIANT_TYPE ("as")), FALSE); g_return_val_if_fail (thumbnail_path != NULL && thumbnail_path[0] != '\0', FALSE); photos_debug (PHOTOS_DEBUG_THUMBNAILER, "Handling GenerateThumbnail for %s", uri); pipeline_uris = g_variant_dup_strv (pipeline_uris_variant, NULL); cancellable = g_cancellable_new (); g_hash_table_insert (self->cancellables, g_object_ref (invocation), g_object_ref (cancellable)); g_application_hold (G_APPLICATION (self)); photos_thumbnailer_generate_thumbnail_async (self, uri, mime_type, orientation, original_height, original_width, (const gchar *const *) pipeline_uris, thumbnail_path, thumbnail_size, cancellable, photos_thumbnailer_handle_generate_thumbnail_generate_thumbnail, g_object_ref (invocation)); return TRUE; }
static gboolean photos_thumbnailer_handle_cancel (PhotosThumbnailer *self, GDBusMethodInvocation *invocation, guint serial) { GCancellable *cancellable; GDBusConnection *connection; GDBusMethodInvocation *invocation_ongoing; GHashTableIter iter; g_return_val_if_fail (PHOTOS_IS_THUMBNAILER (self), FALSE); g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), FALSE); photos_debug (PHOTOS_DEBUG_THUMBNAILER, "Handling Cancel for %u", serial); g_application_hold (G_APPLICATION (self)); connection = g_dbus_method_invocation_get_connection (invocation); g_hash_table_iter_init (&iter, self->cancellables); while (g_hash_table_iter_next (&iter, (gpointer *) &invocation_ongoing, (gpointer *) &cancellable)) { GDBusConnection *connection_ongoing; GDBusMessage *message_ongoing; guint32 serial_ongoing; connection_ongoing = g_dbus_method_invocation_get_connection (invocation_ongoing); message_ongoing = g_dbus_method_invocation_get_message (invocation_ongoing); serial_ongoing = g_dbus_message_get_serial (message_ongoing); if (connection == connection_ongoing && (guint32) serial == serial_ongoing) { g_cancellable_cancel (cancellable); photos_thumbnailer_dbus_complete_cancel (self->skeleton, invocation); goto out; } } g_dbus_method_invocation_return_error_literal (invocation, PHOTOS_ERROR, 0, "Invalid serial"); out: photos_debug (PHOTOS_DEBUG_THUMBNAILER, "Completed Cancel"); g_application_release (G_APPLICATION (self)); return TRUE; }
static gboolean la_handler_service_handle_consumer_lifecycle_request (ShutdownConsumer *consumer, GDBusMethodInvocation *invocation, guint request, guint request_id, ShutdownClient *client) { LAHandlerServiceData *data; LAHandlerService *service; gchar *unit_name; g_return_val_if_fail (IS_SHUTDOWN_CONSUMER (consumer), FALSE); g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), FALSE); g_return_val_if_fail (IS_SHUTDOWN_CLIENT (client), FALSE); /* get the service from the shutdown client */ service = g_object_get_data (G_OBJECT (client), "la-handler-service"); /* look up the unit name associated with this shutdown client */ unit_name = g_hash_table_lookup (service->clients_to_units, client); if (unit_name != NULL) { data = la_handler_service_data_new (service, NULL, request_id); /* stop this unit now */ job_manager_stop (service->job_manager, unit_name, NULL, la_handler_service_handle_consumer_lifecycle_request_finish, data); /* let the NSM know that we are working on this request */ shutdown_consumer_complete_lifecycle_request (consumer, invocation, NSM_ERROR_STATUS_RESPONSE_PENDING); } else { /* NSM asked us to shutdown a shutdown consumer we did not register; * make it aware by returning an error */ shutdown_consumer_complete_lifecycle_request (consumer, invocation, NSM_ERROR_STATUS_ERROR); } return TRUE; }
/** * g_dbus_method_invocation_return_error_valist: * @invocation: A #GDBusMethodInvocation. * @domain: A #GQuark for the #GError error domain. * @code: The error code. * @format: printf()-style format. * @var_args: #va_list of parameters for @format. * * Like g_dbus_method_invocation_return_error() but intended for * language bindings. * * This method will free @invocation, you cannot use it afterwards. * * Since: 2.26 */ void g_dbus_method_invocation_return_error_valist (GDBusMethodInvocation *invocation, GQuark domain, gint code, const gchar *format, va_list var_args) { gchar *literal_message; g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); g_return_if_fail (format != NULL); literal_message = g_strdup_vprintf (format, var_args); g_dbus_method_invocation_return_error_literal (invocation, domain, code, literal_message); g_free (literal_message); }
/** * g_dbus_method_invocation_return_error: * @invocation: A #GDBusMethodInvocation. * @domain: A #GQuark for the #GError error domain. * @code: The error code. * @format: printf()-style format. * @...: Parameters for @format. * * Finishes handling a D-Bus method call by returning an error. * * See g_dbus_error_encode_gerror() for details about what error name * will be returned on the wire. In a nutshell, if the given error is * registered using g_dbus_error_register_error() the name given * during registration is used. Otherwise, a name of the form * <literal>org.gtk.GDBus.UnmappedGError.Quark...</literal> is * used. This provides transparent mapping of #GError between * applications using GDBus. * * If you are writing an application intended to be portable, * <emphasis>always</emphasis> register errors with g_dbus_error_register_error() * or use g_dbus_method_invocation_return_dbus_error(). * * This method will free @invocation, you cannot use it afterwards. * * Since: 2.26 */ void g_dbus_method_invocation_return_error (GDBusMethodInvocation *invocation, GQuark domain, gint code, const gchar *format, ...) { va_list var_args; g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); g_return_if_fail (format != NULL); va_start (var_args, format); g_dbus_method_invocation_return_error_valist (invocation, domain, code, format, var_args); va_end (var_args); }
/** * g_dbus_method_invocation_return_dbus_error: * @invocation: A #GDBusMethodInvocation. * @error_name: A valid D-Bus error name. * @error_message: A valid D-Bus error message. * * Finishes handling a D-Bus method call by returning an error. * * This method will free @invocation, you cannot use it afterwards. * * Since: 2.26 */ void g_dbus_method_invocation_return_dbus_error (GDBusMethodInvocation *invocation, const gchar *error_name, const gchar *error_message) { GDBusMessage *reply; g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); g_return_if_fail (error_name != NULL && g_dbus_is_name (error_name)); g_return_if_fail (error_message != NULL); if (G_UNLIKELY (_g_dbus_debug_return ())) { _g_dbus_debug_print_lock (); g_print ("========================================================================\n" "GDBus-debug:Return:\n" " >>>> METHOD ERROR %s\n" " message `%s'\n" " in response to %s.%s()\n" " on object %s\n" " to name %s\n" " reply-serial %d\n", error_name, error_message, invocation->interface_name, invocation->method_name, invocation->object_path, invocation->sender, g_dbus_message_get_serial (invocation->message)); _g_dbus_debug_print_unlock (); } reply = g_dbus_message_new_method_error_literal (invocation->message, error_name, error_message); g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); g_object_unref (reply); g_object_unref (invocation); }
/** * g_dbus_method_invocation_get_object_path: * @invocation: A #GDBusMethodInvocation. * * Gets the object path the method was invoked on. * * Returns: A string. Do not free, it is owned by @invocation. * * Since: 2.26 */ const gchar * g_dbus_method_invocation_get_object_path (GDBusMethodInvocation *invocation) { g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); return invocation->object_path; }
static void g_dbus_method_invocation_return_value_internal (GDBusMethodInvocation *invocation, GVariant *parameters, GUnixFDList *fd_list) { GDBusMessage *reply; GError *error; g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE)); if (parameters == NULL) parameters = g_variant_new_tuple (NULL, 0); /* if we have introspection data, check that the signature of @parameters is correct */ if (invocation->method_info != NULL) { GVariantType *type; type = _g_dbus_compute_complete_signature (invocation->method_info->out_args); if (!g_variant_is_of_type (parameters, type)) { gchar *type_string = g_variant_type_dup_string (type); g_warning ("Type of return value is incorrect: expected '%s', got '%s''", type_string, g_variant_get_type_string (parameters)); g_variant_type_free (type); g_free (type_string); goto out; } g_variant_type_free (type); } /* property_info is only non-NULL if set that way from * GDBusConnection, so this must be the case of async property * handling on either 'Get', 'Set' or 'GetAll'. */ if (invocation->property_info != NULL) { if (g_str_equal (invocation->method_name, "Get")) { GVariant *nested; if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(v)"))) { g_warning ("Type of return value for property 'Get' call should be '(v)' but got '%s'", g_variant_get_type_string (parameters)); goto out; } /* Go deeper and make sure that the value inside of the * variant matches the property type. */ g_variant_get (parameters, "(v)", &nested); if (!g_str_equal (g_variant_get_type_string (nested), invocation->property_info->signature)) { g_warning ("Value returned from property 'Get' call for '%s' should be '%s' but is '%s'", invocation->property_info->name, invocation->property_info->signature, g_variant_get_type_string (nested)); g_variant_unref (nested); goto out; } g_variant_unref (nested); } else if (g_str_equal (invocation->method_name, "GetAll")) { if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(a{sv})"))) { g_warning ("Type of return value for property 'GetAll' call should be '(a{sv})' but got '%s'", g_variant_get_type_string (parameters)); goto out; } /* Could iterate the list of properties and make sure that all * of them are actually on the interface and with the correct * types, but let's not do that for now... */ } else if (g_str_equal (invocation->method_name, "Set")) { if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE_UNIT)) { g_warning ("Type of return value for property 'Set' call should be '()' but got '%s'", g_variant_get_type_string (parameters)); goto out; } } else g_assert_not_reached (); } if (G_UNLIKELY (_g_dbus_debug_return ())) { _g_dbus_debug_print_lock (); g_print ("========================================================================\n" "GDBus-debug:Return:\n" " >>>> METHOD RETURN\n" " in response to %s.%s()\n" " on object %s\n" " to name %s\n" " reply-serial %d\n", invocation->interface_name, invocation->method_name, invocation->object_path, invocation->sender, g_dbus_message_get_serial (invocation->message)); _g_dbus_debug_print_unlock (); } reply = g_dbus_message_new_method_reply (invocation->message); g_dbus_message_set_body (reply, parameters); #ifdef G_OS_UNIX if (fd_list != NULL) g_dbus_message_set_unix_fd_list (reply, fd_list); #endif error = NULL; if (!g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error)) { g_warning ("Error sending message: %s", error->message); g_error_free (error); } g_object_unref (reply); out: g_object_unref (invocation); }
/** * g_dbus_method_invocation_get_property_info: * @invocation: A #GDBusMethodInvocation * * Gets information about the property that this method call is for, if * any. * * This will only be set in the case of an invocation in response to a * property Get or Set call that has been directed to the method call * handler for an object on account of its property_get() or * property_set() vtable pointers being unset. * * See #GDBusInterfaceVTable for more information. * * If the call was GetAll, %NULL will be returned. * * Returns: (transfer none): a #GDBusPropertyInfo or %NULL * * Since: 2.38 */ const GDBusPropertyInfo * g_dbus_method_invocation_get_property_info (GDBusMethodInvocation *invocation) { g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); return invocation->property_info; }
/** * g_dbus_method_invocation_return_value: * @invocation: A #GDBusMethodInvocation. * @parameters: A #GVariant tuple with out parameters for the method or %NULL if not passing any parameters. * * Finishes handling a D-Bus method call by returning @parameters. * If the @parameters GVariant is floating, it is consumed. * * It is an error if @parameters is not of the right format. * * This method will free @invocation, you cannot use it afterwards. * * Since: 2.26 */ void g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation, GVariant *parameters) { GDBusMessage *reply; GError *error; g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE)); if (parameters == NULL) parameters = g_variant_new_tuple (NULL, 0); /* if we have introspection data, check that the signature of @parameters is correct */ if (invocation->method_info != NULL) { GVariantType *type; type = _g_dbus_compute_complete_signature (invocation->method_info->out_args); if (!g_variant_is_of_type (parameters, type)) { gchar *type_string = g_variant_type_dup_string (type); g_warning (_("Type of return value is incorrect, got `%s', expected `%s'"), g_variant_get_type_string (parameters), type_string); g_variant_type_free (type); g_free (type_string); goto out; } g_variant_type_free (type); } if (G_UNLIKELY (_g_dbus_debug_return ())) { _g_dbus_debug_print_lock (); g_print ("========================================================================\n" "GDBus-debug:Return:\n" " >>>> METHOD RETURN\n" " in response to %s.%s()\n" " on object %s\n" " to name %s\n" " reply-serial %d\n", invocation->interface_name, invocation->method_name, invocation->object_path, invocation->sender, g_dbus_message_get_serial (invocation->message)); _g_dbus_debug_print_unlock (); } reply = g_dbus_message_new_method_reply (invocation->message); g_dbus_message_set_body (reply, parameters); error = NULL; if (!g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error)) { g_warning (_("Error sending message: %s"), error->message); g_error_free (error); } g_object_unref (reply); out: g_object_unref (invocation); }
/** * g_dbus_method_invocation_get_user_data: (skip) * @invocation: A #GDBusMethodInvocation. * * Gets the @user_data #gpointer passed to g_dbus_connection_register_object(). * * Returns: A #gpointer. * * Since: 2.26 */ gpointer g_dbus_method_invocation_get_user_data (GDBusMethodInvocation *invocation) { g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); return invocation->user_data; }
/** * g_dbus_method_invocation_get_parameters: * @invocation: A #GDBusMethodInvocation. * * Gets the parameters of the method invocation. If there are no input * parameters then this will return a GVariant with 0 children rather than NULL. * * Returns: (transfer none): A #GVariant tuple. Do not unref this because it is owned by @invocation. * * Since: 2.26 */ GVariant * g_dbus_method_invocation_get_parameters (GDBusMethodInvocation *invocation) { g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); return invocation->parameters; }
/** * g_dbus_method_invocation_get_message: * @invocation: A #GDBusMethodInvocation. * * Gets the #GDBusMessage for the method invocation. This is useful if * you need to use low-level protocol features, such as UNIX file * descriptor passing, that cannot be properly expressed in the * #GVariant API. * * See <xref linkend="gdbus-server"/> and <xref * linkend="gdbus-unix-fd-client"/> for an example of how to use this * low-level API to send and receive UNIX file descriptors. * * Returns: (transfer none): #GDBusMessage. Do not free, it is owned by @invocation. * * Since: 2.26 */ GDBusMessage * g_dbus_method_invocation_get_message (GDBusMethodInvocation *invocation) { g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); return invocation->message; }
/** * g_dbus_method_invocation_get_connection: * @invocation: A #GDBusMethodInvocation. * * Gets the #GDBusConnection the method was invoked on. * * Returns: (transfer none):A #GDBusConnection. Do not free, it is owned by @invocation. * * Since: 2.26 */ GDBusConnection * g_dbus_method_invocation_get_connection (GDBusMethodInvocation *invocation) { g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); return invocation->connection; }
/** * g_dbus_method_invocation_get_interface_name: * @invocation: A #GDBusMethodInvocation. * * Gets the name of the D-Bus interface the method was invoked on. * * Returns: A string. Do not free, it is owned by @invocation. * * Since: 2.26 */ const gchar * g_dbus_method_invocation_get_interface_name (GDBusMethodInvocation *invocation) { g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); return invocation->interface_name; }
static gboolean la_handler_service_handle_register (LAHandler *interface, GDBusMethodInvocation *invocation, const gchar *unit, NSMShutdownType shutdown_mode, guint timeout, LAHandlerService *service) { ShutdownConsumer *consumer; ShutdownClient *client; GError *error = NULL; const gchar *existing_bus_name; const gchar *existing_object_path; gchar *bus_name; gchar *object_path; g_return_val_if_fail (IS_LA_HANDLER (interface), FALSE); g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), FALSE); g_return_val_if_fail (unit != NULL && *unit != '\0', FALSE); g_return_val_if_fail (LA_HANDLER_IS_SERVICE (service), FALSE); if (shutdown_mode != NSM_SHUTDOWN_TYPE_NORMAL && shutdown_mode != NSM_SHUTDOWN_TYPE_FAST && shutdown_mode != (NSM_SHUTDOWN_TYPE_NORMAL | NSM_SHUTDOWN_TYPE_FAST)) { /* the shutdown mode is invalid */ DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING ("Failed to register legacy application: " "invalid shutdown mode"), DLT_INT (shutdown_mode)); la_handler_complete_register (interface, invocation); return TRUE; } /* find out if we have a shutdown client for this unit already */ client = g_hash_table_lookup (service->units_to_clients, unit); if (client != NULL) { /* there already is a shutdown client for the unit, so simply * re-register its client with the new shutdown mode and timeout */ /* extract information from the client */ existing_bus_name = shutdown_client_get_bus_name (client); existing_object_path = shutdown_client_get_object_path (client); /* temporarily store a reference to the legacy app handler service object * in the invocation object */ g_object_set_data_full (G_OBJECT (invocation), "la-handler-service", g_object_ref (service), (GDestroyNotify) g_object_unref); /* re-register the shutdown consumer with the NSM Consumer */ nsm_consumer_call_register_shutdown_client (service->nsm_consumer, existing_bus_name, existing_object_path, shutdown_mode, timeout, NULL, la_handler_service_handle_register_finish, invocation); } else { /* create a new shutdown client and consumer for the unit */ bus_name = "org.genivi.NodeStartupController1"; object_path = g_strdup_printf ("%s/%u", service->prefix, service->index); client = shutdown_client_new (bus_name, object_path, shutdown_mode, timeout); consumer = shutdown_consumer_skeleton_new (); shutdown_client_set_consumer (client, consumer); /* remember the legacy app handler service object in shutdown client */ g_object_set_data_full (G_OBJECT (client), "la-handler-service", g_object_ref (service), (GDestroyNotify) g_object_unref); /* implement the LifecycleRequest method of the shutdown consumer */ g_signal_connect (consumer, "handle-lifecycle-request", G_CALLBACK (la_handler_service_handle_consumer_lifecycle_request), client); /* associate the shutdown client with the unit name */ g_hash_table_insert (service->units_to_clients, g_strdup (unit), g_object_ref (client)); g_hash_table_insert (service->clients_to_units, g_object_ref (client), g_strdup (unit)); /* export the shutdown consumer on the bus */ g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (consumer), service->connection, object_path, &error); if (error != NULL) { DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING ("Failed to export shutdown consumer on the bus:"), DLT_STRING (error->message)); g_error_free (error); } /* temporarily store a reference to the legacy app handler service object * in the invocation object */ g_object_set_data_full (G_OBJECT (invocation), "la-handler-service", g_object_ref (service), (GDestroyNotify) g_object_unref); /* register the shutdown consumer with the NSM Consumer */ nsm_consumer_call_register_shutdown_client (service->nsm_consumer, bus_name, object_path, shutdown_mode, timeout, NULL, la_handler_service_handle_register_finish, invocation); /* free strings and release the shutdown consumer */ g_free (object_path); g_object_unref (consumer); /* increment the counter for our shutdown consumer object paths */ service->index++; } return TRUE; }