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);
}
Пример #4
0
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);
}
Пример #6
0
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;
}
Пример #7
0
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;
}