⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gupnp-service.c

📁 另一 UPNP SDK 支持在UNIX/LINUX上运行。 UPnP是一种网络协议
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (C) 2007, 2008 OpenedHand Ltd. * * Author: Jorn Baayen <jorn@openedhand.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//** * SECTION:gupnp-service * @short_description: Class for service implementations. * * #GUPnPService allows for handling incoming actions and state variable * notification. #GUPnPService implements the #GUPnPServiceInfo interface. */#include <gobject/gvaluecollector.h>#include <gmodule.h>#include <libsoup/soup-date.h>#include <uuid/uuid.h>#include <string.h>#include "gupnp-service.h"#include "gupnp-root-device.h"#include "gupnp-context-private.h"#include "gupnp-marshal.h"#include "gupnp-error.h"#include "http-headers.h"#include "gena-protocol.h"#include "xml-util.h"#include "gvalue-util.h"G_DEFINE_TYPE (GUPnPService,               gupnp_service,               GUPNP_TYPE_SERVICE_INFO);struct _GUPnPServicePrivate {        GUPnPRootDevice *root_device;        guint            notify_available_id;        GHashTable      *subscriptions;        GList           *state_variables;        GQueue          *notify_queue;        gboolean         notify_frozen;};enum {        PROP_0,        PROP_ROOT_DEVICE};enum {        ACTION_INVOKED,        QUERY_VARIABLE,        NOTIFY_FAILED,        LAST_SIGNAL};static guint signals[LAST_SIGNAL];static char *create_property_set (GQueue *queue);static voidnotify_subscriber   (gpointer key,                     gpointer value,                     gpointer user_data);typedef struct {        GUPnPService *service;        GList        *callbacks;        char         *sid;        int           seq;        guint         timeout_id;        GList        *pending_messages; /* Pending SoupMessages from this                                           subscription */} SubscriptionData;static voidsubscription_data_free (SubscriptionData *data){        GUPnPContext *context;        SoupSession *session;        context = gupnp_service_info_get_context                        (GUPNP_SERVICE_INFO (data->service));        session = _gupnp_context_get_session (context);        /* Cancel pending messages */        while (data->pending_messages) {                SoupMessage *msg;                msg = data->pending_messages->data;                soup_session_cancel_message (session,                                             msg,                                             SOUP_STATUS_CANCELLED);                data->pending_messages =                        g_list_delete_link (data->pending_messages,                                            data->pending_messages);        }               /* Further cleanup */        while (data->callbacks) {                g_free (data->callbacks->data);                data->callbacks = g_list_delete_link (data->callbacks,                                                      data->callbacks);        }        g_free (data->sid);        if (data->timeout_id)                g_source_remove (data->timeout_id);        g_slice_free (SubscriptionData, data);}typedef struct {        char  *variable;        GValue value;} NotifyData;static voidnotify_data_free (NotifyData *data){        g_free (data->variable);        g_value_unset (&data->value);        g_slice_free (NotifyData, data);}struct _GUPnPServiceAction {        const char  *name;        SoupMessage *msg;        xmlNode     *node;        GString     *response_str;};GTypegupnp_service_action_get_type (void){        static GType our_type = 0;        if (our_type == 0)                our_type = g_pointer_type_register_static                                        ("GUPnPServiceAction");        return our_type;}/** * 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: 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 * @Varargs: tuples of argument name, argument type, and argument value * location, terminated with %NULL. * * Retrieves the specified action arguments. **/voidgupnp_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. **/voidgupnp_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, &copy_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_value * @action: A #GUPnPServiceAction * @argument: The name of the argument to retrieve * @value: The #GValue to store the value of the argument, initialized * to the correct type. * * Retrieves the value of @argument into @value. **/voidgupnp_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 retreive '%s' argument of '%s' action",                           argument,                           action->name);}/** * gupnp_service_action_set * @action: A #GUPnPServiceAction * @Varargs: tuples of return value name, return value type, and * actual return value, terminated with %NULL. * * Sets the specified action return values. **/voidgupnp_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. **/voidgupnp_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, 0, &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_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. **/voidgupnp_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. **/voidgupnp_service_action_return (GUPnPServiceAction *action){        g_return_if_fail (action != NULL);        soup_message_set_status (action->msg, SOUP_STATUS_OK);}/** * 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. **/voidgupnp_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");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -