summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Georg <mail@jensge.org>2021-05-29 00:55:49 +0200
committerJens Georg <mail@jensge.org>2021-07-03 18:45:31 +0200
commit704f39a9d43d447fe437c5a261adf07bccfcb5f1 (patch)
treefe06cb9a74b01ad6c6b4248e827376a231771b19
parentfebe4243c542dfeb6d4042195d6e63302dd1dd1d (diff)
downloadgupnp-704f39a9d43d447fe437c5a261adf07bccfcb5f1.tar.gz
ServiceProxyAction: Change serialization
- Arguemnts are stored in the ServiceProxyAction - Serialization is done before creating the message
-rw-r--r--libgupnp/gupnp-service-proxy-action-private.h12
-rw-r--r--libgupnp/gupnp-service-proxy-action.c85
-rw-r--r--libgupnp/gupnp-service-proxy.c60
3 files changed, 100 insertions, 57 deletions
diff --git a/libgupnp/gupnp-service-proxy-action-private.h b/libgupnp/gupnp-service-proxy-action-private.h
index f455be5..f20e382 100644
--- a/libgupnp/gupnp-service-proxy-action-private.h
+++ b/libgupnp/gupnp-service-proxy-action-private.h
@@ -131,7 +131,6 @@ G_BEGIN_DECLS
} \
} G_STMT_END
-
struct _GUPnPServiceProxyAction {
GUPnPServiceProxy *proxy;
char *name;
@@ -146,8 +145,12 @@ struct _GUPnPServiceProxyAction {
GUPnPServiceProxyActionCallback callback;
gpointer user_data;
- GError *error; /* If non-NULL, description of error that
- occurred when preparing message */
+ GError *error; /* If non-NULL, description of error that
+ occurred when preparing message */
+
+ GPtrArray *args;
+ GHashTable *arg_map;
+ gboolean pending;
};
G_GNUC_INTERNAL GUPnPServiceProxyAction *
@@ -158,6 +161,9 @@ gupnp_service_proxy_action_get_result_valist (GUPnPServiceProxyAction *action,
GError **error,
va_list var_args);
+G_GNUC_INTERNAL void
+gupnp_service_proxy_action_serialize (GUPnPServiceProxyAction *action,
+ const char *service_type);
G_END_DECLS
#endif /* GUPNP_SERVICE_PROXY_ACTION_H */
diff --git a/libgupnp/gupnp-service-proxy-action.c b/libgupnp/gupnp-service-proxy-action.c
index 241bb8a..35e2fb9 100644
--- a/libgupnp/gupnp-service-proxy-action.c
+++ b/libgupnp/gupnp-service-proxy-action.c
@@ -16,6 +16,20 @@
#include "gvalue-util.h"
#include "xml-util.h"
+struct _ActionArgument {
+ char *name;
+ GValue value;
+};
+typedef struct _ActionArgument ActionArgument;
+
+void
+action_argument_free (ActionArgument* arg)
+{
+ g_free (arg->name);
+ g_value_unset (&arg->value);
+ g_free (arg);
+}
+
/* Reads a value into the parameter name and initialised GValue pair
* from @response */
static void
@@ -187,6 +201,8 @@ gupnp_service_proxy_action_new_internal (const char *action) {
ret = g_atomic_rc_box_new0 (GUPnPServiceProxyAction);
ret->name = g_strdup (action);
+ ret->args = g_ptr_array_new_with_free_func((GDestroyNotify)action_argument_free);
+ ret->arg_map = g_hash_table_new (g_str_hash, g_str_equal);
return ret;
}
@@ -219,6 +235,8 @@ action_dispose (GUPnPServiceProxyAction *action)
g_string_free (action->msg_str, TRUE);
action->msg_str = NULL;
}
+ g_hash_table_destroy (action->arg_map);
+ g_ptr_array_unref (action->args);
g_free (action->name);
}
@@ -237,14 +255,13 @@ G_DEFINE_BOXED_TYPE (GUPnPServiceProxyAction,
/* Writes a parameter name and GValue pair to @msg */
static void
-write_in_parameter (const char *arg_name,
- GValue *value,
+write_in_parameter (ActionArgument *arg,
GString *msg_str)
{
/* Write parameter pair */
- xml_util_start_element (msg_str, arg_name);
- gvalue_util_value_append_to_xml_string (value, msg_str);
- xml_util_end_element (msg_str, arg_name);
+ xml_util_start_element (msg_str, arg->name);
+ gvalue_util_value_append_to_xml_string (&arg->value, msg_str);
+ xml_util_end_element (msg_str, arg->name);
}
static void
@@ -387,34 +404,62 @@ gupnp_service_proxy_action_new_from_list (const char *action_name,
{
GUPnPServiceProxyAction *action;
GList *names, *values;
+ guint position;
action = gupnp_service_proxy_action_new_internal (action_name);
+
+ /* Arguments */
+ for (names = in_names, values = in_values, position = 0;
+ names && values;
+ names = names->next, values = values->next, position++) {
+ GValue *val = values->data;
+
+ ActionArgument *arg = g_new0 (ActionArgument, 1);
+ arg->name = g_strdup (names->data);
+ g_value_init (&arg->value, G_VALUE_TYPE (val));
+ g_value_copy (val, &arg->value);
+ g_hash_table_insert (action->arg_map,
+ arg->name,
+ GUINT_TO_POINTER (position));
+ g_ptr_array_add (action->args, arg);
+ }
+
+ return action;
+}
+
+void
+gupnp_service_proxy_action_serialize (GUPnPServiceProxyAction *action,
+ const char *service_type)
+{
+ if (action->msg_str != NULL) {
+ g_string_free (action->msg_str, TRUE);
+ }
action->msg_str = xml_util_new_string ();
g_string_append (action->msg_str,
"<?xml version=\"1.0\"?>"
"<s:Envelope xmlns:s="
- "\"http://schemas.xmlsoap.org/soap/envelope/\" "
- "s:encodingStyle="
- "\"http://schemas.xmlsoap.org/soap/encoding/\">"
+ "\"http://schemas.xmlsoap.org/soap/envelope/\" "
+ "s:encodingStyle="
+ "\"http://schemas.xmlsoap.org/soap/encoding/\">"
"<s:Body>");
action->header_pos = action->msg_str->len;
- /* Arguments */
- for (names = in_names, values = in_values;
- names && values;
- names=names->next, values = values->next) {
- GValue* val = values->data;
-
- write_in_parameter (names->data,
- val,
- action->msg_str);
- }
+ g_ptr_array_foreach (action->args,
+ (GFunc) write_in_parameter,
+ action->msg_str);
- /* Finish and send off */
write_footer (action);
- return action;
+ g_string_insert (action->msg_str, action->header_pos, "<u:");
+ action->header_pos += strlen ("<u:");
+ g_string_insert (action->msg_str, action->header_pos, action->name);
+ action->header_pos += strlen (action->name);
+ g_string_insert (action->msg_str, action->header_pos, " xmlns:u=\"");
+ action->header_pos += strlen (" xmlns:u=\"");
+ g_string_insert (action->msg_str, action->header_pos, service_type);
+ action->header_pos += strlen (service_type);
+ g_string_insert (action->msg_str, action->header_pos, "\">");
}
/**
diff --git a/libgupnp/gupnp-service-proxy.c b/libgupnp/gupnp-service-proxy.c
index 1b84f15..eae446b 100644
--- a/libgupnp/gupnp-service-proxy.c
+++ b/libgupnp/gupnp-service-proxy.c
@@ -617,10 +617,12 @@ on_action_cancelled (GCancellable *cancellable, gpointer user_data)
}
}
+
+
/* Begins a basic action message */
static void
prepare_action_msg (GUPnPServiceProxy *proxy,
- GUPnPServiceProxyAction *ret,
+ GUPnPServiceProxyAction *action,
GCancellable *cancellable)
{
GUPnPServiceProxyPrivate *priv;
@@ -628,27 +630,26 @@ prepare_action_msg (GUPnPServiceProxy *proxy,
const char *service_type;
priv = gupnp_service_proxy_get_instance_private (proxy);
+ action->proxy = proxy;
+ g_object_add_weak_pointer (G_OBJECT (proxy), (gpointer *)&(action->proxy));
- ret->proxy = proxy;
- g_object_add_weak_pointer (G_OBJECT (proxy), (gpointer *)&(ret->proxy));
-
- priv->pending_actions = g_list_prepend (priv->pending_actions, ret);
+ priv->pending_actions = g_list_prepend (priv->pending_actions, action);
if (cancellable != NULL) {
- ret->cancellable = g_object_ref (cancellable);
+ action->cancellable = g_object_ref (cancellable);
} else {
- ret->cancellable = g_cancellable_new ();
+ action->cancellable = g_cancellable_new ();
}
- ret->cancellable_connection_id = g_cancellable_connect (ret->cancellable,
+ action->cancellable_connection_id = g_cancellable_connect (action->cancellable,
G_CALLBACK (on_action_cancelled),
- ret,
+ action,
NULL);
/* Make sure we have a service type */
service_type = gupnp_service_info_get_service_type
(GUPNP_SERVICE_INFO (proxy));
if (service_type == NULL) {
- ret->error = g_error_new (GUPNP_SERVER_ERROR,
+ action->error = g_error_new (GUPNP_SERVER_ERROR,
GUPNP_SERVER_ERROR_OTHER,
"No service type defined");
@@ -670,12 +671,10 @@ prepare_action_msg (GUPnPServiceProxy *proxy,
control_url);
g_free (control_url);
- ret->msg = soup_message_new (SOUP_METHOD_POST, local_control_url);
+ action->msg = soup_message_new (SOUP_METHOD_POST, local_control_url);
g_free (local_control_url);
- }
-
- if (ret->msg == NULL) {
- ret->error = g_error_new (GUPNP_SERVER_ERROR,
+ } else {
+ action->error = g_error_new (GUPNP_SERVER_ERROR,
GUPNP_SERVER_ERROR_INVALID_URL,
"No valid control URL defined");
@@ -683,37 +682,29 @@ prepare_action_msg (GUPnPServiceProxy *proxy,
}
/* Specify action */
- full_action = g_strdup_printf ("\"%s#%s\"", service_type, ret->name);
- soup_message_headers_append (ret->msg->request_headers,
+ full_action = g_strdup_printf ("\"%s#%s\"", service_type, action->name);
+ soup_message_headers_append (action->msg->request_headers,
"SOAPAction",
full_action);
g_free (full_action);
/* Specify language */
- http_request_set_accept_language (ret->msg);
+ http_request_set_accept_language (action->msg);
/* Accept gzip encoding */
- soup_message_headers_append (ret->msg->request_headers,
+ soup_message_headers_append (action->msg->request_headers,
"Accept-Encoding", "gzip");
- g_string_insert (ret->msg_str, ret->header_pos, "<u:");
- ret->header_pos += strlen("<u:");
- g_string_insert (ret->msg_str, ret->header_pos, ret->name);
- ret->header_pos += strlen (ret->name);
- g_string_insert (ret->msg_str, ret->header_pos, " xmlns:u=\"");
- ret->header_pos += strlen(" xmlns:u=\"");
- g_string_insert (ret->msg_str, ret->header_pos, service_type);
- ret->header_pos += strlen (service_type);
- g_string_insert (ret->msg_str, ret->header_pos, "\">");
-
- soup_message_set_request (ret->msg,
+ gupnp_service_proxy_action_serialize (action, service_type);
+
+ soup_message_set_request (action->msg,
"text/xml; charset=\"utf-8\"",
SOUP_MEMORY_TAKE,
- ret->msg_str->str,
- ret->msg_str->len);
+ action->msg_str->str,
+ action->msg_str->len);
- g_string_free (ret->msg_str, FALSE);
- ret->msg_str = NULL;
+ g_string_free (action->msg_str, FALSE);
+ action->msg_str = NULL;
}
static void
@@ -807,6 +798,7 @@ gupnp_service_proxy_action_queue_task (GTask *task)
action->msg,
(SoupSessionCallback) action_task_got_response,
task);
+ action->pending = TRUE;
}
/**