diff options
author | Jens Georg <mail@jensge.org> | 2021-05-29 00:55:49 +0200 |
---|---|---|
committer | Jens Georg <mail@jensge.org> | 2021-07-03 18:45:31 +0200 |
commit | 704f39a9d43d447fe437c5a261adf07bccfcb5f1 (patch) | |
tree | fe06cb9a74b01ad6c6b4248e827376a231771b19 | |
parent | febe4243c542dfeb6d4042195d6e63302dd1dd1d (diff) | |
download | gupnp-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.h | 12 | ||||
-rw-r--r-- | libgupnp/gupnp-service-proxy-action.c | 85 | ||||
-rw-r--r-- | libgupnp/gupnp-service-proxy.c | 60 |
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; } /** |