[gupnp] service: Move ServiceAction code into its own file
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gupnp] service: Move ServiceAction code into its own file
- Date: Sat, 20 Nov 2021 17:52:40 +0000 (UTC)
commit 5d7279c75fde7cb6fa07a76d2a986a0cde303cd5
Author: Jens Georg <mail jensge org>
Date: Thu Nov 4 22:34:52 2021 +0100
service: Move ServiceAction code into its own file
libgupnp/gupnp-service-action.c | 609 +++++++++++++++++++++++++++++++++++++++
libgupnp/gupnp-service-private.h | 5 +
libgupnp/gupnp-service.c | 598 --------------------------------------
libgupnp/meson.build | 1 +
4 files changed, 615 insertions(+), 598 deletions(-)
---
diff --git a/libgupnp/gupnp-service-action.c b/libgupnp/gupnp-service-action.c
new file mode 100644
index 0000000..2c50e94
--- /dev/null
+++ b/libgupnp/gupnp-service-action.c
@@ -0,0 +1,609 @@
+#include <config.h>
+
+#include "gupnp-error.h"
+#include "gupnp-service-private.h"
+#include "gupnp-service.h"
+#include "gupnp-xml-doc.h"
+#include "gvalue-util.h"
+#include "http-headers.h"
+#include "xml-util.h"
+
+GUPnPServiceAction *
+gupnp_service_action_new ()
+{
+ return g_atomic_rc_box_new0 (GUPnPServiceAction);
+}
+
+GUPnPServiceAction *
+gupnp_service_action_ref (GUPnPServiceAction *action)
+{
+ g_return_val_if_fail (action, NULL);
+
+ return g_atomic_rc_box_acquire (action);
+}
+
+static void
+action_dispose (GUPnPServiceAction *action)
+{
+ g_free (action->name);
+ g_object_unref (action->msg);
+ g_object_unref (action->context);
+ g_object_unref (action->doc);
+}
+
+void
+gupnp_service_action_unref (GUPnPServiceAction *action)
+{
+ g_return_if_fail (action);
+
+ g_atomic_rc_box_release_full (action, (GDestroyNotify) action_dispose);
+}
+
+/**
+ * gupnp_service_action_get_type:
+ *
+ * Get the gtype for GUPnPServiceActon
+ *
+ * Return value: The gtype of GUPnPServiceAction
+ **/
+GType
+gupnp_service_action_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ our_type = g_boxed_type_register_static (
+ "GUPnPServiceAction",
+ (GBoxedCopyFunc) gupnp_service_action_ref,
+ (GBoxedFreeFunc) gupnp_service_action_unref);
+
+ return our_type;
+}
+
+static void
+finalize_action (GUPnPServiceAction *action)
+{
+ SoupServer *server;
+
+ /* Embed action->response_str in a SOAP document */
+ g_string_prepend (action->response_str,
+ "<?xml version=\"1.0\"?>"
+ "<s:Envelope xmlns:s="
+ "\"http://schemas.xmlsoap.org/soap/envelope/\" "
+ "s:encodingStyle="
+ "\"http://schemas.xmlsoap.org/soap/encoding/\">"
+ "<s:Body>");
+
+ if (action->msg->status_code != SOUP_STATUS_INTERNAL_SERVER_ERROR) {
+ g_string_append (action->response_str, "</u:");
+ g_string_append (action->response_str, action->name);
+ g_string_append (action->response_str, "Response>");
+ }
+
+ g_string_append (action->response_str,
+ "</s:Body>"
+ "</s:Envelope>");
+
+ soup_message_headers_replace (action->msg->response_headers,
+ "Content-Type",
+ "text/xml; charset=\"utf-8\"");
+
+ if (action->accept_gzip && action->response_str->len > 1024) {
+ http_response_set_body_gzip (action->msg,
+ action->response_str->str,
+ action->response_str->len);
+ g_string_free (action->response_str, TRUE);
+ } else {
+ soup_message_body_append (action->msg->response_body,
+ SOUP_MEMORY_TAKE,
+ action->response_str->str,
+ action->response_str->len);
+ g_string_free (action->response_str, FALSE);
+ }
+
+ soup_message_headers_append (action->msg->response_headers, "Ext", "");
+
+ /* Server header on response */
+ soup_message_headers_append (
+ action->msg->response_headers,
+ "Server",
+ gssdp_client_get_server_id (GSSDP_CLIENT (action->context)));
+
+ /* Tell soup server that response is now ready */
+ server = gupnp_context_get_server (action->context);
+ soup_server_unpause_message (server, action->msg);
+
+ /* Cleanup */
+ gupnp_service_action_unref (action);
+}
+
+/**
+ * gupnp_service_action_get_name:
+ * @action: A #GUPnPServiceAction
+ *
+ * Get the name of @action.
+ *
+ * Return value: The name of @action
+ **/
+const char *
+gupnp_service_action_get_name (GUPnPServiceAction *action)
+{
+ g_return_val_if_fail (action != NULL, NULL);
+
+ return action->name;
+}
+
+/**
+ * gupnp_service_action_get_locales:
+ * @action: A #GUPnPServiceAction
+ *
+ * Get an ordered (preferred first) #GList of locales preferred by
+ * the client. Free list and elements after use.
+ *
+ * Return value: (element-type utf8) (transfer full): A #GList of #char*
+ * locale names.
+ **/
+GList *
+gupnp_service_action_get_locales (GUPnPServiceAction *action)
+{
+ g_return_val_if_fail (action != NULL, NULL);
+
+ return http_request_get_accept_locales (action->msg);
+}
+
+/**
+ * gupnp_service_action_get:
+ * @action: A #GUPnPServiceAction
+ * @...: tuples of argument name, argument type, and argument value
+ * location, terminated with %NULL.
+ *
+ * Retrieves the specified action arguments.
+ **/
+void
+gupnp_service_action_get (GUPnPServiceAction *action, ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (action != NULL);
+
+ va_start (var_args, action);
+ gupnp_service_action_get_valist (action, var_args);
+ va_end (var_args);
+}
+
+/**
+ * gupnp_service_action_get_valist:
+ * @action: A #GUPnPServiceAction
+ * @var_args: va_list of tuples of argument name, argument type, and argument
+ * value location.
+ *
+ * See gupnp_service_action_get(); this version takes a va_list for
+ * use by language bindings.
+ **/
+void
+gupnp_service_action_get_valist (GUPnPServiceAction *action, va_list var_args)
+{
+ const char *arg_name;
+ GType arg_type;
+ GValue value = {
+ 0,
+ };
+ char *copy_error;
+
+ g_return_if_fail (action != NULL);
+
+ copy_error = NULL;
+
+ arg_name = va_arg (var_args, const char *);
+ while (arg_name) {
+ arg_type = va_arg (var_args, GType);
+ g_value_init (&value, arg_type);
+
+ gupnp_service_action_get_value (action, arg_name, &value);
+
+ G_VALUE_LCOPY (&value, var_args, 0, ©_error);
+
+ g_value_unset (&value);
+
+ if (copy_error) {
+ g_warning ("Error lcopying value: %s\n", copy_error);
+
+ g_free (copy_error);
+ }
+
+ arg_name = va_arg (var_args, const char *);
+ }
+}
+
+/**
+ * gupnp_service_action_get_values:
+ * @action: A #GUPnPServiceAction
+ * @arg_names: (element-type utf8) : A #GList of argument names as string
+ * @arg_types: (element-type GType): A #GList of argument types as #GType
+ *
+ * A variant of #gupnp_service_action_get that uses #GList instead of varargs.
+ *
+ * Return value: (element-type GValue) (transfer full): The values as #GList of
+ * #GValue. g_list_free() the returned list and g_value_unset() and g_slice_free()
+ * each element.
+ *
+ * Since: 0.14.0
+ **/
+GList *
+gupnp_service_action_get_values (GUPnPServiceAction *action,
+ GList *arg_names,
+ GList *arg_types)
+{
+ GList *arg_values;
+ guint i;
+
+ g_return_val_if_fail (action != NULL, NULL);
+
+ arg_values = NULL;
+
+ for (i = 0; i < g_list_length (arg_names); i++) {
+ const char *arg_name;
+ GType arg_type;
+ GValue *arg_value;
+
+ arg_name = (const char *) g_list_nth_data (arg_names, i);
+ arg_type = (GType) g_list_nth_data (arg_types, i);
+
+ arg_value = g_slice_new0 (GValue);
+ g_value_init (arg_value, arg_type);
+
+ gupnp_service_action_get_value (action, arg_name, arg_value);
+
+ arg_values = g_list_append (arg_values, arg_value);
+ }
+
+ return arg_values;
+}
+
+/**
+ * gupnp_service_action_get_value: (skip)
+ * @action: A #GUPnPServiceAction
+ * @argument: The name of the argument to retrieve
+ * @value: (inout):The #GValue to store the value of the argument, initialized
+ * to the correct type.
+ *
+ * Retrieves the value of @argument into @value.
+ **/
+void
+gupnp_service_action_get_value (GUPnPServiceAction *action,
+ const char *argument,
+ GValue *value)
+{
+ xmlNode *node;
+ gboolean found;
+
+ g_return_if_fail (action != NULL);
+ g_return_if_fail (argument != NULL);
+ g_return_if_fail (value != NULL);
+
+ found = FALSE;
+ for (node = action->node->children; node; node = node->next) {
+ if (strcmp ((char *) node->name, argument) != 0)
+ continue;
+
+ found = gvalue_util_set_value_from_xml_node (value, node);
+
+ break;
+ }
+
+ if (!found)
+ g_warning ("Failed to retrieve '%s' argument of '%s' action",
+ argument,
+ action->name);
+}
+
+/**
+ * gupnp_service_action_get_gvalue: (rename-to gupnp_service_action_get_value)
+ * @action: A #GUPnPServiceAction
+ * @argument: The name of the argument to retrieve
+ * @type: The type of argument to retrieve
+ *
+ * Retrieves the value of @argument into a GValue of type @type and returns it.
+ * The method exists only and only to satify PyGI, please use
+ * gupnp_service_action_get_value() and ignore this if possible.
+ *
+ * Return value: (transfer full): Value as #GValue associated with @action.
+ * g_value_unset() and g_slice_free() it after usage.
+ *
+ * Since: 0.14.0
+ **/
+GValue *
+gupnp_service_action_get_gvalue (GUPnPServiceAction *action,
+ const char *argument,
+ GType type)
+{
+ GValue *val;
+
+ val = g_slice_new0 (GValue);
+ g_value_init (val, type);
+
+ gupnp_service_action_get_value (action, argument, val);
+
+ return val;
+}
+
+/**
+ * gupnp_service_action_get_argument_count:
+ * @action: A #GUPnPServiceAction
+ *
+ * Get the number of IN arguments from the @action and return it.
+ *
+ * Return value: The number of IN arguments from the @action.
+ *
+ * Since: 0.18.0
+ */
+guint
+gupnp_service_action_get_argument_count (GUPnPServiceAction *action)
+{
+ return action->argument_count;
+}
+
+/**
+ * gupnp_service_action_set:
+ * @action: A #GUPnPServiceAction
+ * @...: tuples of return value name, return value type, and
+ * actual return value, terminated with %NULL.
+ *
+ * Sets the specified action return values.
+ **/
+void
+gupnp_service_action_set (GUPnPServiceAction *action, ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (action != NULL);
+
+ va_start (var_args, action);
+ gupnp_service_action_set_valist (action, var_args);
+ va_end (var_args);
+}
+
+/**
+ * gupnp_service_action_set_valist:
+ * @action: A #GUPnPServiceAction
+ * @var_args: va_list of tuples of return value name, return value type, and
+ * actual return value.
+ *
+ * See gupnp_service_action_set(); this version takes a va_list for
+ * use by language bindings.
+ **/
+void
+gupnp_service_action_set_valist (GUPnPServiceAction *action, va_list var_args)
+{
+ const char *arg_name;
+ GType arg_type;
+ GValue value = {
+ 0,
+ };
+ char *collect_error;
+
+ g_return_if_fail (action != NULL);
+
+ collect_error = NULL;
+
+ arg_name = va_arg (var_args, const char *);
+ while (arg_name) {
+ arg_type = va_arg (var_args, GType);
+ g_value_init (&value, arg_type);
+
+ G_VALUE_COLLECT (&value,
+ var_args,
+ G_VALUE_NOCOPY_CONTENTS,
+ &collect_error);
+ if (!collect_error) {
+ gupnp_service_action_set_value (action,
+ arg_name,
+ &value);
+
+ g_value_unset (&value);
+
+ } else {
+ g_warning ("Error collecting value: %s\n",
+ collect_error);
+
+ g_free (collect_error);
+ }
+
+ arg_name = va_arg (var_args, const char *);
+ }
+}
+
+/**
+ * gupnp_service_action_set_values:
+ * @action: A #GUPnPServiceAction
+ * @arg_names: (element-type utf8) (transfer none): A #GList of argument names
+ * @arg_values: (element-type GValue) (transfer none): The #GList of values (as
+ * #GValue<!-- -->s) that line up with @arg_names.
+ *
+ * Sets the specified action return values.
+ *
+ * Since: 0.14.0
+ **/
+void
+gupnp_service_action_set_values (GUPnPServiceAction *action,
+ GList *arg_names,
+ GList *arg_values)
+{
+ g_return_if_fail (action != NULL);
+ g_return_if_fail (arg_names != NULL);
+ g_return_if_fail (arg_values != NULL);
+ g_return_if_fail (g_list_length (arg_names) ==
+ g_list_length (arg_values));
+
+ if (action->msg->status_code == SOUP_STATUS_INTERNAL_SERVER_ERROR) {
+ g_warning ("Calling gupnp_service_action_set_value() after "
+ "having called gupnp_service_action_return_error() "
+ "is not allowed.");
+
+ return;
+ }
+
+ /* Append to response */
+ for (; arg_names; arg_names = arg_names->next) {
+ const char *arg_name;
+ GValue *value;
+
+ arg_name = arg_names->data;
+ value = arg_values->data;
+
+ xml_util_start_element (action->response_str, arg_name);
+ gvalue_util_value_append_to_xml_string (value,
+ action->response_str);
+ xml_util_end_element (action->response_str, arg_name);
+
+ arg_values = arg_values->next;
+ }
+}
+
+/**
+ * gupnp_service_action_set_value:
+ * @action: A #GUPnPServiceAction
+ * @argument: The name of the return value to retrieve
+ * @value: The #GValue to store the return value
+ *
+ * Sets the value of @argument to @value.
+ **/
+void
+gupnp_service_action_set_value (GUPnPServiceAction *action,
+ const char *argument,
+ const GValue *value)
+{
+ g_return_if_fail (action != NULL);
+ g_return_if_fail (argument != NULL);
+ g_return_if_fail (value != NULL);
+
+ if (action->msg->status_code == SOUP_STATUS_INTERNAL_SERVER_ERROR) {
+ g_warning ("Calling gupnp_service_action_set_value() after "
+ "having called gupnp_service_action_return_error() "
+ "is not allowed.");
+
+ return;
+ }
+
+ /* Append to response */
+ xml_util_start_element (action->response_str, argument);
+ gvalue_util_value_append_to_xml_string (value, action->response_str);
+ xml_util_end_element (action->response_str, argument);
+}
+
+/**
+ * gupnp_service_action_return:
+ * @action: A #GUPnPServiceAction
+ *
+ * Return succesfully.
+ **/
+void
+gupnp_service_action_return (GUPnPServiceAction *action)
+{
+ g_return_if_fail (action != NULL);
+
+ soup_message_set_status (action->msg, SOUP_STATUS_OK);
+
+ finalize_action (action);
+}
+
+/**
+ * gupnp_service_action_return_error:
+ * @action: A #GUPnPServiceAction
+ * @error_code: The error code
+ * @error_description: The error description, or %NULL if @error_code is
+ * one of #GUPNP_CONTROL_ERROR_INVALID_ACTION,
+ * #GUPNP_CONTROL_ERROR_INVALID_ARGS, #GUPNP_CONTROL_ERROR_OUT_OF_SYNC or
+ * #GUPNP_CONTROL_ERROR_ACTION_FAILED, in which case a description is
+ * provided automatically.
+ *
+ * Return @error_code.
+ **/
+void
+gupnp_service_action_return_error (GUPnPServiceAction *action,
+ guint error_code,
+ const char *error_description)
+{
+ g_return_if_fail (action != NULL);
+
+ switch (error_code) {
+ case GUPNP_CONTROL_ERROR_INVALID_ACTION:
+ if (error_description == NULL)
+ error_description = "Invalid Action";
+
+ break;
+ case GUPNP_CONTROL_ERROR_INVALID_ARGS:
+ if (error_description == NULL)
+ error_description = "Invalid Args";
+
+ break;
+ case GUPNP_CONTROL_ERROR_OUT_OF_SYNC:
+ if (error_description == NULL)
+ error_description = "Out of Sync";
+
+ break;
+ case GUPNP_CONTROL_ERROR_ACTION_FAILED:
+ if (error_description == NULL)
+ error_description = "Action Failed";
+
+ break;
+ default:
+ g_return_if_fail (error_description != NULL);
+ break;
+ }
+
+ /* Replace response_str with a SOAP Fault */
+ g_string_erase (action->response_str, 0, -1);
+
+ xml_util_start_element (action->response_str, "s:Fault");
+
+ xml_util_start_element (action->response_str, "faultcode");
+ g_string_append (action->response_str, "s:Client");
+ xml_util_end_element (action->response_str, "faultcode");
+
+ xml_util_start_element (action->response_str, "faultstring");
+ g_string_append (action->response_str, "UPnPError");
+ xml_util_end_element (action->response_str, "faultstring");
+
+ xml_util_start_element (action->response_str, "detail");
+
+ xml_util_start_element (action->response_str,
+ "UPnPError "
+ "xmlns=\"urn:schemas-upnp-org:control-1-0\"");
+
+ xml_util_start_element (action->response_str, "errorCode");
+ g_string_append_printf (action->response_str, "%u", error_code);
+ xml_util_end_element (action->response_str, "errorCode");
+
+ xml_util_start_element (action->response_str, "errorDescription");
+ xml_util_add_content (action->response_str, error_description);
+ xml_util_end_element (action->response_str, "errorDescription");
+
+ xml_util_end_element (action->response_str, "UPnPError");
+ xml_util_end_element (action->response_str, "detail");
+
+ xml_util_end_element (action->response_str, "s:Fault");
+
+ soup_message_set_status (action->msg,
+ SOUP_STATUS_INTERNAL_SERVER_ERROR);
+
+ finalize_action (action);
+}
+
+/**
+ * gupnp_service_action_get_message:
+ * @action: A #GUPnPServiceAction
+ *
+ * Get the #SoupMessage associated with @action. Mainly intended for
+ * applications to be able to read HTTP headers received from clients.
+ *
+ * Return value: (transfer full): #SoupMessage associated with @action. Unref
+ * after using it.
+ *
+ * Since: 0.14.0
+ **/
+SoupMessage *
+gupnp_service_action_get_message (GUPnPServiceAction *action)
+{
+ return g_object_ref (action->msg);
+}
diff --git a/libgupnp/gupnp-service-private.h b/libgupnp/gupnp-service-private.h
index 1915505..0d6772b 100644
--- a/libgupnp/gupnp-service-private.h
+++ b/libgupnp/gupnp-service-private.h
@@ -9,6 +9,11 @@
#ifndef GUPNP_SERVICE_PRIVATE_H
#define GUPNP_SERVICE_PRIVATE_H
+#include "gupnp-context.h"
+#include "gupnp-xml-doc.h"
+
+#include <libsoup/soup.h>
+
struct _GUPnPServiceAction {
GUPnPContext *context;
diff --git a/libgupnp/gupnp-service.c b/libgupnp/gupnp-service.c
index 67b3d43..1eeb96f 100644
--- a/libgupnp/gupnp-service.c
+++ b/libgupnp/gupnp-service.c
@@ -204,604 +204,6 @@ notify_data_free (NotifyData *data)
g_slice_free (NotifyData, data);
}
-GUPnPServiceAction *
-gupnp_service_action_new ()
-{
- return g_atomic_rc_box_new0 (GUPnPServiceAction);
-}
-
-GUPnPServiceAction *
-gupnp_service_action_ref (GUPnPServiceAction *action)
-{
- g_return_val_if_fail (action, NULL);
-
- return g_atomic_rc_box_acquire (action);
-}
-
-static void
-action_dispose (GUPnPServiceAction *action)
-{
- g_free (action->name);
- g_object_unref (action->msg);
- g_object_unref (action->context);
- g_object_unref (action->doc);
-}
-
-void
-gupnp_service_action_unref (GUPnPServiceAction *action)
-{
- g_return_if_fail (action);
-
- g_atomic_rc_box_release_full (action, (GDestroyNotify) action_dispose);
-}
-
-/**
- * gupnp_service_action_get_type:
- *
- * Get the gtype for GUPnPServiceActon
- *
- * Return value: The gtype of GUPnPServiceAction
- **/
-GType
-gupnp_service_action_get_type (void)
-{
- static GType our_type = 0;
-
- if (our_type == 0)
- our_type = g_boxed_type_register_static
- ("GUPnPServiceAction",
- (GBoxedCopyFunc) gupnp_service_action_ref,
- (GBoxedFreeFunc) gupnp_service_action_unref);
-
- return our_type;
-}
-
-static void
-finalize_action (GUPnPServiceAction *action)
-{
- SoupServer *server;
-
- /* Embed action->response_str in a SOAP document */
- g_string_prepend (action->response_str,
- "<?xml version=\"1.0\"?>"
- "<s:Envelope xmlns:s="
- "\"http://schemas.xmlsoap.org/soap/envelope/\" "
- "s:encodingStyle="
- "\"http://schemas.xmlsoap.org/soap/encoding/\">"
- "<s:Body>");
-
- if (action->msg->status_code != SOUP_STATUS_INTERNAL_SERVER_ERROR) {
- g_string_append (action->response_str, "</u:");
- g_string_append (action->response_str, action->name);
- g_string_append (action->response_str, "Response>");
- }
-
- g_string_append (action->response_str,
- "</s:Body>"
- "</s:Envelope>");
-
- soup_message_headers_replace (action->msg->response_headers,
- "Content-Type",
- "text/xml; charset=\"utf-8\"");
-
- if (action->accept_gzip && action->response_str->len > 1024) {
- http_response_set_body_gzip (action->msg,
- action->response_str->str,
- action->response_str->len);
- g_string_free (action->response_str, TRUE);
- } else {
- soup_message_body_append (action->msg->response_body,
- SOUP_MEMORY_TAKE,
- action->response_str->str,
- action->response_str->len);
- g_string_free (action->response_str, FALSE);
- }
-
- soup_message_headers_append (action->msg->response_headers, "Ext", "");
-
- /* Server header on response */
- soup_message_headers_append
- (action->msg->response_headers,
- "Server",
- gssdp_client_get_server_id
- (GSSDP_CLIENT (action->context)));
-
- /* Tell soup server that response is now ready */
- server = gupnp_context_get_server (action->context);
- soup_server_unpause_message (server, action->msg);
-
- /* Cleanup */
- gupnp_service_action_unref (action);
-}
-
-/**
- * gupnp_service_action_get_name:
- * @action: A #GUPnPServiceAction
- *
- * Get the name of @action.
- *
- * Return value: The name of @action
- **/
-const char *
-gupnp_service_action_get_name (GUPnPServiceAction *action)
-{
- g_return_val_if_fail (action != NULL, NULL);
-
- return action->name;
-}
-
-/**
- * gupnp_service_action_get_locales:
- * @action: A #GUPnPServiceAction
- *
- * Get an ordered (preferred first) #GList of locales preferred by
- * the client. Free list and elements after use.
- *
- * Return value: (element-type utf8) (transfer full): A #GList of #char*
- * locale names.
- **/
-GList *
-gupnp_service_action_get_locales (GUPnPServiceAction *action)
-{
- g_return_val_if_fail (action != NULL, NULL);
-
- return http_request_get_accept_locales (action->msg);
-}
-
-/**
- * gupnp_service_action_get:
- * @action: A #GUPnPServiceAction
- * @...: tuples of argument name, argument type, and argument value
- * location, terminated with %NULL.
- *
- * Retrieves the specified action arguments.
- **/
-void
-gupnp_service_action_get (GUPnPServiceAction *action,
- ...)
-{
- va_list var_args;
-
- g_return_if_fail (action != NULL);
-
- va_start (var_args, action);
- gupnp_service_action_get_valist (action, var_args);
- va_end (var_args);
-}
-
-/**
- * gupnp_service_action_get_valist:
- * @action: A #GUPnPServiceAction
- * @var_args: va_list of tuples of argument name, argument type, and argument
- * value location.
- *
- * See gupnp_service_action_get(); this version takes a va_list for
- * use by language bindings.
- **/
-void
-gupnp_service_action_get_valist (GUPnPServiceAction *action,
- va_list var_args)
-{
- const char *arg_name;
- GType arg_type;
- GValue value = {0, };
- char *copy_error;
-
- g_return_if_fail (action != NULL);
-
- copy_error = NULL;
-
- arg_name = va_arg (var_args, const char *);
- while (arg_name) {
- arg_type = va_arg (var_args, GType);
- g_value_init (&value, arg_type);
-
- gupnp_service_action_get_value (action, arg_name, &value);
-
- G_VALUE_LCOPY (&value, var_args, 0, ©_error);
-
- g_value_unset (&value);
-
- if (copy_error) {
- g_warning ("Error lcopying value: %s\n", copy_error);
-
- g_free (copy_error);
- }
-
- arg_name = va_arg (var_args, const char *);
- }
-}
-
-/**
- * gupnp_service_action_get_values:
- * @action: A #GUPnPServiceAction
- * @arg_names: (element-type utf8) : A #GList of argument names as string
- * @arg_types: (element-type GType): A #GList of argument types as #GType
- *
- * A variant of #gupnp_service_action_get that uses #GList instead of varargs.
- *
- * Return value: (element-type GValue) (transfer full): The values as #GList of
- * #GValue. g_list_free() the returned list and g_value_unset() and g_slice_free()
- * each element.
- *
- * Since: 0.14.0
- **/
-GList *
-gupnp_service_action_get_values (GUPnPServiceAction *action,
- GList *arg_names,
- GList *arg_types)
-{
- GList *arg_values;
- guint i;
-
- g_return_val_if_fail (action != NULL, NULL);
-
- arg_values = NULL;
-
- for (i = 0; i < g_list_length (arg_names); i++) {
- const char *arg_name;
- GType arg_type;
- GValue *arg_value;
-
- arg_name = (const char *) g_list_nth_data (arg_names, i);
- arg_type = (GType) g_list_nth_data (arg_types, i);
-
- arg_value = g_slice_new0 (GValue);
- g_value_init (arg_value, arg_type);
-
- gupnp_service_action_get_value (action, arg_name, arg_value);
-
- arg_values = g_list_append (arg_values, arg_value);
- }
-
- return arg_values;
-}
-
-/**
- * gupnp_service_action_get_value: (skip)
- * @action: A #GUPnPServiceAction
- * @argument: The name of the argument to retrieve
- * @value: (inout):The #GValue to store the value of the argument, initialized
- * to the correct type.
- *
- * Retrieves the value of @argument into @value.
- **/
-void
-gupnp_service_action_get_value (GUPnPServiceAction *action,
- const char *argument,
- GValue *value)
-{
- xmlNode *node;
- gboolean found;
-
- g_return_if_fail (action != NULL);
- g_return_if_fail (argument != NULL);
- g_return_if_fail (value != NULL);
-
- found = FALSE;
- for (node = action->node->children; node; node = node->next) {
- if (strcmp ((char *) node->name, argument) != 0)
- continue;
-
- found = gvalue_util_set_value_from_xml_node (value, node);
-
- break;
- }
-
- if (!found)
- g_warning ("Failed to retrieve '%s' argument of '%s' action",
- argument,
- action->name);
-}
-
-/**
- * gupnp_service_action_get_gvalue: (rename-to gupnp_service_action_get_value)
- * @action: A #GUPnPServiceAction
- * @argument: The name of the argument to retrieve
- * @type: The type of argument to retrieve
- *
- * Retrieves the value of @argument into a GValue of type @type and returns it.
- * The method exists only and only to satify PyGI, please use
- * gupnp_service_action_get_value() and ignore this if possible.
- *
- * Return value: (transfer full): Value as #GValue associated with @action.
- * g_value_unset() and g_slice_free() it after usage.
- *
- * Since: 0.14.0
- **/
-GValue *
-gupnp_service_action_get_gvalue (GUPnPServiceAction *action,
- const char *argument,
- GType type)
-{
- GValue *val;
-
- val = g_slice_new0 (GValue);
- g_value_init (val, type);
-
- gupnp_service_action_get_value (action, argument, val);
-
- return val;
-}
-
-/**
- * gupnp_service_action_get_argument_count:
- * @action: A #GUPnPServiceAction
- *
- * Get the number of IN arguments from the @action and return it.
- *
- * Return value: The number of IN arguments from the @action.
- *
- * Since: 0.18.0
- */
-guint
-gupnp_service_action_get_argument_count (GUPnPServiceAction *action)
-{
- return action->argument_count;
-}
-
-/**
- * gupnp_service_action_set:
- * @action: A #GUPnPServiceAction
- * @...: tuples of return value name, return value type, and
- * actual return value, terminated with %NULL.
- *
- * Sets the specified action return values.
- **/
-void
-gupnp_service_action_set (GUPnPServiceAction *action,
- ...)
-{
- va_list var_args;
-
- g_return_if_fail (action != NULL);
-
- va_start (var_args, action);
- gupnp_service_action_set_valist (action, var_args);
- va_end (var_args);
-}
-
-/**
- * gupnp_service_action_set_valist:
- * @action: A #GUPnPServiceAction
- * @var_args: va_list of tuples of return value name, return value type, and
- * actual return value.
- *
- * See gupnp_service_action_set(); this version takes a va_list for
- * use by language bindings.
- **/
-void
-gupnp_service_action_set_valist (GUPnPServiceAction *action,
- va_list var_args)
-{
- const char *arg_name;
- GType arg_type;
- GValue value = {0, };
- char *collect_error;
-
- g_return_if_fail (action != NULL);
-
- collect_error = NULL;
-
- arg_name = va_arg (var_args, const char *);
- while (arg_name) {
- arg_type = va_arg (var_args, GType);
- g_value_init (&value, arg_type);
-
- G_VALUE_COLLECT (&value, var_args, G_VALUE_NOCOPY_CONTENTS,
- &collect_error);
- if (!collect_error) {
- gupnp_service_action_set_value (action,
- arg_name, &value);
-
- g_value_unset (&value);
-
- } else {
- g_warning ("Error collecting value: %s\n",
- collect_error);
-
- g_free (collect_error);
- }
-
- arg_name = va_arg (var_args, const char *);
- }
-}
-
-/**
- * gupnp_service_action_set_values:
- * @action: A #GUPnPServiceAction
- * @arg_names: (element-type utf8) (transfer none): A #GList of argument names
- * @arg_values: (element-type GValue) (transfer none): The #GList of values (as
- * #GValue<!-- -->s) that line up with @arg_names.
- *
- * Sets the specified action return values.
- *
- * Since: 0.14.0
- **/
-void
-gupnp_service_action_set_values (GUPnPServiceAction *action,
- GList *arg_names,
- GList *arg_values)
-{
- g_return_if_fail (action != NULL);
- g_return_if_fail (arg_names != NULL);
- g_return_if_fail (arg_values != NULL);
- g_return_if_fail (g_list_length (arg_names) ==
- g_list_length (arg_values));
-
- if (action->msg->status_code == SOUP_STATUS_INTERNAL_SERVER_ERROR) {
- g_warning ("Calling gupnp_service_action_set_value() after "
- "having called gupnp_service_action_return_error() "
- "is not allowed.");
-
- return;
- }
-
- /* Append to response */
- for (; arg_names; arg_names = arg_names->next) {
- const char *arg_name;
- GValue *value;
-
- arg_name = arg_names->data;
- value = arg_values->data;
-
- xml_util_start_element (action->response_str, arg_name);
- gvalue_util_value_append_to_xml_string (value,
- action->response_str);
- xml_util_end_element (action->response_str, arg_name);
-
- arg_values = arg_values->next;
- }
-}
-
-/**
- * gupnp_service_action_set_value:
- * @action: A #GUPnPServiceAction
- * @argument: The name of the return value to retrieve
- * @value: The #GValue to store the return value
- *
- * Sets the value of @argument to @value.
- **/
-void
-gupnp_service_action_set_value (GUPnPServiceAction *action,
- const char *argument,
- const GValue *value)
-{
- g_return_if_fail (action != NULL);
- g_return_if_fail (argument != NULL);
- g_return_if_fail (value != NULL);
-
- if (action->msg->status_code == SOUP_STATUS_INTERNAL_SERVER_ERROR) {
- g_warning ("Calling gupnp_service_action_set_value() after "
- "having called gupnp_service_action_return_error() "
- "is not allowed.");
-
- return;
- }
-
- /* Append to response */
- xml_util_start_element (action->response_str, argument);
- gvalue_util_value_append_to_xml_string (value, action->response_str);
- xml_util_end_element (action->response_str, argument);
-}
-
-/**
- * gupnp_service_action_return:
- * @action: A #GUPnPServiceAction
- *
- * Return succesfully.
- **/
-void
-gupnp_service_action_return (GUPnPServiceAction *action)
-{
- g_return_if_fail (action != NULL);
-
- soup_message_set_status (action->msg, SOUP_STATUS_OK);
-
- finalize_action (action);
-}
-
-/**
- * gupnp_service_action_return_error:
- * @action: A #GUPnPServiceAction
- * @error_code: The error code
- * @error_description: The error description, or %NULL if @error_code is
- * one of #GUPNP_CONTROL_ERROR_INVALID_ACTION,
- * #GUPNP_CONTROL_ERROR_INVALID_ARGS, #GUPNP_CONTROL_ERROR_OUT_OF_SYNC or
- * #GUPNP_CONTROL_ERROR_ACTION_FAILED, in which case a description is
- * provided automatically.
- *
- * Return @error_code.
- **/
-void
-gupnp_service_action_return_error (GUPnPServiceAction *action,
- guint error_code,
- const char *error_description)
-{
- g_return_if_fail (action != NULL);
-
- switch (error_code) {
- case GUPNP_CONTROL_ERROR_INVALID_ACTION:
- if (error_description == NULL)
- error_description = "Invalid Action";
-
- break;
- case GUPNP_CONTROL_ERROR_INVALID_ARGS:
- if (error_description == NULL)
- error_description = "Invalid Args";
-
- break;
- case GUPNP_CONTROL_ERROR_OUT_OF_SYNC:
- if (error_description == NULL)
- error_description = "Out of Sync";
-
- break;
- case GUPNP_CONTROL_ERROR_ACTION_FAILED:
- if (error_description == NULL)
- error_description = "Action Failed";
-
- break;
- default:
- g_return_if_fail (error_description != NULL);
- break;
- }
-
- /* Replace response_str with a SOAP Fault */
- g_string_erase (action->response_str, 0, -1);
-
- xml_util_start_element (action->response_str, "s:Fault");
-
- xml_util_start_element (action->response_str, "faultcode");
- g_string_append (action->response_str, "s:Client");
- xml_util_end_element (action->response_str, "faultcode");
-
- xml_util_start_element (action->response_str, "faultstring");
- g_string_append (action->response_str, "UPnPError");
- xml_util_end_element (action->response_str, "faultstring");
-
- xml_util_start_element (action->response_str, "detail");
-
- xml_util_start_element (action->response_str,
- "UPnPError "
- "xmlns=\"urn:schemas-upnp-org:control-1-0\"");
-
- xml_util_start_element (action->response_str, "errorCode");
- g_string_append_printf (action->response_str, "%u", error_code);
- xml_util_end_element (action->response_str, "errorCode");
-
- xml_util_start_element (action->response_str, "errorDescription");
- xml_util_add_content (action->response_str, error_description);
- xml_util_end_element (action->response_str, "errorDescription");
-
- xml_util_end_element (action->response_str, "UPnPError");
- xml_util_end_element (action->response_str, "detail");
-
- xml_util_end_element (action->response_str, "s:Fault");
-
- soup_message_set_status (action->msg,
- SOUP_STATUS_INTERNAL_SERVER_ERROR);
-
- finalize_action (action);
-}
-
-/**
- * gupnp_service_action_get_message:
- * @action: A #GUPnPServiceAction
- *
- * Get the #SoupMessage associated with @action. Mainly intended for
- * applications to be able to read HTTP headers received from clients.
- *
- * Return value: (transfer full): #SoupMessage associated with @action. Unref
- * after using it.
- *
- * Since: 0.14.0
- **/
-SoupMessage *
-gupnp_service_action_get_message (GUPnPServiceAction *action)
-{
- return g_object_ref (action->msg);
-}
-
static void
gupnp_service_init (GUPnPService *service)
{
diff --git a/libgupnp/meson.build b/libgupnp/meson.build
index af74d94..89688e6 100644
--- a/libgupnp/meson.build
+++ b/libgupnp/meson.build
@@ -79,6 +79,7 @@ sources = files(
'gupnp-resource-factory.c',
'gupnp-root-device.c',
'gupnp-service.c',
+ 'gupnp-service-action.c',
'gupnp-service-info.c',
'gupnp-service-introspection.c',
'gupnp-service-proxy.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]