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

📄 gupnp-service-proxy.c

📁 另一 UPNP SDK 支持在UNIX/LINUX上运行。 UPnP是一种网络协议
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (C) 2006, 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-proxy * @short_description: Proxy class for remote services. * * #GUPnPServiceProxy sends commands to a remote UPnP service and handles * incoming event notifications. #GUPnPServiceProxy implements the * #GUPnPServiceInfo interface. */#include <libsoup/soup.h>#include <gobject/gvaluecollector.h>#include <string.h>#include <locale.h>#include "gupnp-service-proxy.h"#include "gupnp-context-private.h"#include "gupnp-error.h"#include "gupnp-error-private.h"#include "gupnp-types.h"#include "xml-util.h"#include "gena-protocol.h"#include "http-headers.h"#include "gvalue-util.h"G_DEFINE_TYPE (GUPnPServiceProxy,               gupnp_service_proxy,               GUPNP_TYPE_SERVICE_INFO);struct _GUPnPServiceProxyPrivate {        gboolean subscribed;        GList *pending_actions;        char *path; /* Path to this proxy */        char *sid; /* Subscription ID */        guint subscription_timeout_id;        int seq; /* Event sequence number */        GHashTable *notify_hash;        GList *pending_messages; /* Pending SoupMessages from this proxy */        GList *pending_notifies; /* Pending notifications to be sent (xmlDoc*) */        guint notify_idle_id; /* Idle handler ID of notification emiter */};enum {        PROP_0,        PROP_SUBSCRIBED};enum {        SUBSCRIPTION_LOST,        LAST_SIGNAL};static guint signals[LAST_SIGNAL];struct _GUPnPServiceProxyAction {        GUPnPServiceProxy *proxy;        SoupMessage *msg;        GString *msg_str;        GUPnPServiceProxyActionCallback callback;        gpointer user_data;        GError *error;    /* If non-NULL, description of error that                             occurred when preparing message */        va_list var_args; /* The va_list after begin_action_valist has                             gone through it. Used by send_action_valist(). */};typedef struct {        GType type;        GList *callbacks;} NotifyData;typedef struct {        GUPnPServiceProxyNotifyCallback callback;        gpointer user_data;} CallbackData;static voidsubscribe_got_response (SoupSession       *session,                        SoupMessage       *msg,                        GUPnPServiceProxy *proxy);static voidsubscribe (GUPnPServiceProxy *proxy);static voidunsubscribe (GUPnPServiceProxy *proxy);static voidgupnp_service_proxy_action_free (GUPnPServiceProxyAction *action){        action->proxy->priv->pending_actions =                g_list_remove (action->proxy->priv->pending_actions, action);        if (action->msg != NULL)                g_object_unref (action->msg);        g_slice_free (GUPnPServiceProxyAction, action);}static voidnotify_data_free (NotifyData *data){        g_list_free (data->callbacks);        g_slice_free (NotifyData, data);}static voidgupnp_service_proxy_init (GUPnPServiceProxy *proxy){        static int proxy_counter = 0;        proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy,                                                   GUPNP_TYPE_SERVICE_PROXY,                                                   GUPnPServiceProxyPrivate);        /* Generate unique path */        proxy->priv->path = g_strdup_printf ("/ServiceProxy%d", proxy_counter);        proxy_counter++;        /* Set up notify hash */        proxy->priv->notify_hash =                g_hash_table_new_full (g_str_hash,                                       g_str_equal,                                       g_free,                                       (GDestroyNotify) notify_data_free);}static voidgupnp_service_proxy_set_property (GObject      *object,                                  guint         property_id,                                  const GValue *value,                                  GParamSpec   *pspec){        GUPnPServiceProxy *proxy;        proxy = GUPNP_SERVICE_PROXY (object);        switch (property_id) {        case PROP_SUBSCRIBED:                gupnp_service_proxy_set_subscribed                                (proxy, g_value_get_boolean (value));                break;        default:                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);                break;        }}static voidgupnp_service_proxy_get_property (GObject    *object,                                  guint       property_id,                                  GValue     *value,                                  GParamSpec *pspec){        GUPnPServiceProxy *proxy;        proxy = GUPNP_SERVICE_PROXY (object);        switch (property_id) {        case PROP_SUBSCRIBED:                g_value_set_boolean (value,                                     proxy->priv->subscribed);                break;        default:                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);                break;        }}static voidgupnp_service_proxy_dispose (GObject *object){        GUPnPServiceProxy *proxy;        GObjectClass *object_class;        GUPnPContext *context;        SoupSession *session;        proxy = GUPNP_SERVICE_PROXY (object);        /* Unsubscribe */        if (proxy->priv->subscribed) {                unsubscribe (proxy);                proxy->priv->subscribed = FALSE;        }        /* Cancel pending actions */        while (proxy->priv->pending_actions) {                GUPnPServiceProxyAction *action;                action = proxy->priv->pending_actions->data;                gupnp_service_proxy_cancel_action (proxy, action);        }        /* Cancel pending messages */        context = gupnp_service_info_get_context (GUPNP_SERVICE_INFO (proxy));        if (context)                session = _gupnp_context_get_session (context);        else                session = NULL; /* Not the first time dispose is called. */        while (proxy->priv->pending_messages) {                SoupMessage *msg;                msg = proxy->priv->pending_messages->data;                soup_session_cancel_message (session,                                             msg,                                             SOUP_STATUS_CANCELLED);                proxy->priv->pending_messages =                        g_list_delete_link (proxy->priv->pending_messages,                                            proxy->priv->pending_messages);        }        /* Cancel pending notifications */        if (proxy->priv->notify_idle_id) {                g_source_remove (proxy->priv->notify_idle_id);                proxy->priv->notify_idle_id = 0;        }                while (proxy->priv->pending_notifies) {                xmlFreeDoc (proxy->priv->pending_notifies->data);                proxy->priv->pending_notifies = g_list_delete_link (proxy->priv->pending_notifies,                                                                   proxy->priv->pending_notifies);        }                /* Call super */        object_class = G_OBJECT_CLASS (gupnp_service_proxy_parent_class);        object_class->dispose (object);}static voidgupnp_service_proxy_finalize (GObject *object){        GUPnPServiceProxy *proxy;        GObjectClass *object_class;        proxy = GUPNP_SERVICE_PROXY (object);        g_free (proxy->priv->path);        g_hash_table_destroy (proxy->priv->notify_hash);        /* Call super */        object_class = G_OBJECT_CLASS (gupnp_service_proxy_parent_class);        object_class->finalize (object);}static voidgupnp_service_proxy_class_init (GUPnPServiceProxyClass *klass){        GObjectClass *object_class;        object_class = G_OBJECT_CLASS (klass);        object_class->set_property = gupnp_service_proxy_set_property;        object_class->get_property = gupnp_service_proxy_get_property;        object_class->dispose      = gupnp_service_proxy_dispose;        object_class->finalize     = gupnp_service_proxy_finalize;        g_type_class_add_private (klass, sizeof (GUPnPServiceProxyPrivate));        /**         * GUPnPServiceProxy:subscribed         *         * Whether we are subscribed to this service.         **/        g_object_class_install_property                (object_class,                 PROP_SUBSCRIBED,                 g_param_spec_boolean ("subscribed",                                       "Subscribed",                                       "Whether we are subscribed to this "                                       "service",                                       FALSE,                                       G_PARAM_READWRITE |                                       G_PARAM_STATIC_NAME |                                       G_PARAM_STATIC_NICK |                                       G_PARAM_STATIC_BLURB));        /**         * GUPnPServiceProxy::subscription-lost         * @proxy: The #GUPnPServiceProxy that received the signal         * @error: A pointer to a #GError describing why the subscription has         * been lost         *         * Emitted whenever the subscription to this service has been lost due         * to an error condition.         **/        signals[SUBSCRIPTION_LOST] =                g_signal_new ("subscription-lost",                              GUPNP_TYPE_SERVICE_PROXY,                              G_SIGNAL_RUN_LAST,                              G_STRUCT_OFFSET (GUPnPServiceProxyClass,                                               subscription_lost),                              NULL,                              NULL,                              g_cclosure_marshal_VOID__POINTER,                              G_TYPE_NONE,                              1,                              G_TYPE_POINTER);}/** * gupnp_service_proxy_send_action * @proxy: A #GUPnPServiceProxy * @action: An action * @error: The location where to store any error, or %NULL * @Varargs: tuples of in parameter name, in paramater type, and in parameter * value, followed by %NULL, and then tuples of out paramater name, * out parameter type, and out parameter value location, terminated with %NULL * * Sends action @action with parameters @Varargs to the service exposed by * @proxy synchronously. If an error occurred, @error will be set. In case of * a UPnPError the error code will be the same in @error. * * Return value: %TRUE if sending the action was succesful. **/gbooleangupnp_service_proxy_send_action (GUPnPServiceProxy *proxy,                                 const char        *action,                                 GError           **error,                                 ...){        va_list var_args;        gboolean ret;        va_start (var_args, error);        ret = gupnp_service_proxy_send_action_valist (proxy,                                                      action,                                                      error,                                                      var_args);        va_end (var_args);        return ret;}static voidstop_main_loop (GUPnPServiceProxy       *proxy,                GUPnPServiceProxyAction *action,                gpointer                 user_data){        g_main_loop_quit ((GMainLoop *) user_data);}/** * gupnp_service_proxy_send_action_valist * @proxy: A #GUPnPServiceProxy * @action: An action * @error: The location where to store any error, or %NULL * @var_args: va_list of tuples of in parameter name, in paramater type, and in

⌨️ 快捷键说明

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