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

📄 gupnp-service-proxy.c

📁 另一 UPNP SDK 支持在UNIX/LINUX上运行。 UPnP是一种网络协议
💻 C
📖 第 1 页 / 共 5 页
字号:
        g_hash_table_foreach (hash, (GHFunc) read_out_parameter, params);        /* Cleanup */        gupnp_service_proxy_action_free (action);        xmlFreeDoc (response);        return TRUE;}/** * gupnp_service_proxy_cancel_action * @proxy: A #GUPnPServiceProxy * @action: A #GUPnPServiceProxyAction handle * * Cancels @action, freeing the @action handle. **/voidgupnp_service_proxy_cancel_action (GUPnPServiceProxy       *proxy,                                   GUPnPServiceProxyAction *action){        GUPnPContext *context;        SoupSession *session;        g_return_if_fail (GUPNP_IS_SERVICE_PROXY (proxy));        g_return_if_fail (action);        if (action->msg != NULL) {                context = gupnp_service_info_get_context                                        (GUPNP_SERVICE_INFO (proxy));                session = _gupnp_context_get_session (context);                soup_session_cancel_message (session,                                             action->msg,                                             SOUP_STATUS_CANCELLED);        }        if (action->error != NULL)                g_error_free (action->error);        gupnp_service_proxy_action_free (action);}/** * gupnp_service_proxy_add_notify * @proxy: A #GUPnPServiceProxy * @variable: The variable to add notification for * @type: The type of the variable * @callback: The callback to call when @variable changes * @user_data: User data for @callback * * Sets up @callback to be called whenever a change notification for * @variable is recieved. * * Return value: %TRUE on success. **/gbooleangupnp_service_proxy_add_notify (GUPnPServiceProxy              *proxy,                                const char                     *variable,                                GType                           type,                                GUPnPServiceProxyNotifyCallback callback,                                gpointer                        user_data){        NotifyData *data;        CallbackData *callback_data;        g_return_val_if_fail (GUPNP_IS_SERVICE_PROXY (proxy), FALSE);        g_return_val_if_fail (variable, FALSE);        g_return_val_if_fail (type, FALSE);        g_return_val_if_fail (callback, FALSE);        /* See if we already have notifications set up for this variable */        data = g_hash_table_lookup (proxy->priv->notify_hash, variable);        if (data == NULL) {                /* No, create one */                data = g_slice_new (NotifyData);                data->type       = type;                data->callbacks  = NULL;                g_hash_table_insert (proxy->priv->notify_hash,                                     g_strdup (variable),                                     data);        } else {                /* Yes, check that everything is sane .. */                if (data->type != type) {                        g_warning ("A notification already exists for %s, but "                                   "has type %s, not %s.",                                   variable,                                   g_type_name (data->type),                                   g_type_name (type));                        return FALSE;                }        }        /* Append callback */        callback_data = g_slice_new (CallbackData);        callback_data->callback  = callback;        callback_data->user_data = user_data;        data->callbacks = g_list_append (data->callbacks, callback_data);        return TRUE;}/** * gupnp_service_proxy_remove_notify * @proxy: A #GUPnPServiceProxy * @variable: The variable to add notification for * @callback: The callback to call when @variable changes * @user_data: User data for @callback * * Cancels the variable change notification for @callback and @user_data. * * Return value: %TRUE on success. **/gbooleangupnp_service_proxy_remove_notify (GUPnPServiceProxy              *proxy,                                   const char                     *variable,                                   GUPnPServiceProxyNotifyCallback callback,                                   gpointer                        user_data){        NotifyData *data;        gboolean found;        GList *l;        g_return_val_if_fail (GUPNP_IS_SERVICE_PROXY (proxy), FALSE);        g_return_val_if_fail (variable, FALSE);        g_return_val_if_fail (callback, FALSE);        /* Look up NotifyData for variable */        data = g_hash_table_lookup (proxy->priv->notify_hash, variable);        if (data == NULL) {                g_warning ("No notifications found for variable %s",                           variable);                return FALSE;        }        /* Look up our callback-user_data pair */        found = FALSE;        for (l = data->callbacks; l; l = l->next) {                CallbackData *callback_data;                callback_data = l->data;                if (callback_data->callback  == callback &&                    callback_data->user_data == user_data) {                        /* Gotcha! */                        g_slice_free (CallbackData, callback_data);                        data->callbacks =                                g_list_delete_link (data->callbacks, l);                        if (data->callbacks == NULL) {                                /* No callbacks left: Remove from hash */                                g_hash_table_remove (proxy->priv->notify_hash,                                                     data);                        }                        found = TRUE;                        break;                }        }        if (found == FALSE)                g_warning ("No such callback-user_data pair was found");        return found;}/* Emit pending notifications. See comment below on why we do this. */static gbooleanemit_notifications (gpointer user_data){        GUPnPServiceProxy *proxy = user_data;        g_assert (user_data);                while (proxy->priv->pending_notifies != NULL) {                xmlDoc *doc;                xmlNode *node;                doc = proxy->priv->pending_notifies->data;                node = xmlDocGetRootElement (doc);                                /* Iterate over all provided properties */                for (node = node->children; node; node = node->next) {                        xmlNode *var_node;                                                if (strcmp ((char *) node->name, "property") != 0)                                continue;                                                /* property */                        for (var_node = node->children; var_node;                             var_node = var_node->next) {                                NotifyData *data;                                GValue value = {0, };                                GList *l;                                                                data = g_hash_table_lookup                                        (proxy->priv->notify_hash,                                         var_node->name);                                if (data == NULL)                                        continue;                                                                /* Make a GValue of the desired type */                                g_value_init (&value, data->type);                                                                if (!gvalue_util_set_value_from_xml_node                                                        (&value, var_node)) {                                        g_value_unset (&value);                                                                                continue;                                }                                                                /* Call callbacks */                                for (l = data->callbacks; l; l = l->next) {                                        CallbackData *callback_data;                                                                                callback_data = l->data;                                                                                callback_data->callback                                                (proxy,                                                 (const char *) var_node->name,                                                 &value,                                                 callback_data->user_data);                                }                                                                /* Cleanup */                                g_value_unset (&value);                        }                }                                /* Cleanup */                xmlFreeDoc (doc);                proxy->priv->pending_notifies =                        g_list_delete_link (proxy->priv->pending_notifies,                                            proxy->priv->pending_notifies);        }                proxy->priv->notify_idle_id = 0;	return FALSE;}/* * HTTP server received a message. Handle, if this was a NOTIFY * message with our SID. */static voidserver_handler (SoupServer        *soup_server,                SoupMessage       *msg,                 const char        *server_path,                GHashTable        *query,                SoupClientContext *soup_client,                gpointer           user_data){        GUPnPServiceProxy *proxy;        const char *hdr;        int seq;        xmlDoc *doc;        xmlNode *node;        proxy = GUPNP_SERVICE_PROXY (user_data);        if (strcmp (msg->method, GENA_METHOD_NOTIFY) != 0) {                /* We don't implement this method */                soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);                return;        }        hdr = soup_message_headers_get (msg->request_headers, "NT");        if (hdr == NULL || strcmp (hdr, "upnp:event") != 0) {                /* Proper NT header lacking */                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);                return;        }        hdr = soup_message_headers_get (msg->request_headers, "NTS");        if (hdr == NULL || strcmp (hdr, "upnp:propchange") != 0) {                /* Proper NTS header lacking */                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);                return;        }        hdr = soup_message_headers_get (msg->request_headers, "SID");        if (hdr == NULL ||            (proxy->priv->sid && (strcmp (hdr, proxy->priv->sid) != 0))) {                /* No SID or not ours */                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);                return;        }        /* We do not error out if proxy->priv->sid is NIL as the subscription         * response may not have been processed yet. */#if 0        if (!proxy->priv->sid) {                GUPnPContext *context;                GMainContext *main_context;                context = gupnp_service_info_get_context                                        (GUPNP_SERVICE_INFO (proxy));                main_context = gssdp_client_get_main_context                                        (GSSDP_CLIENT (context));                /* Wait. Perhaps the subscription response has not yet                 * been processed. */                g_main_context_iteration (main_context, FALSE);                if (!proxy->priv->sid || strcmp (hdr, proxy->priv->sid) != 0) {                        /* Really not our SID */                        soup_message_set_status                                (msg, SOUP_STATUS_PRECONDITION_FAILED);                        return;                }        }#endif        hdr = soup_message_headers_get (msg->request_headers, "SEQ");        if (hdr == NULL) {                /* No SEQ header */                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);                return;        }        seq = atoi (hdr);        if (seq > proxy->priv->seq) {                /* Oops, we missed a notify. Resubscribe .. */                unsubscribe (proxy);                subscribe (proxy);                /* Message was OK otherwise */                soup_message_set_status (msg, SOUP_STATUS_OK);                return;        }        /* Increment our own event sequence number */        if (proxy->priv->seq < G_MAXINT32)                proxy->priv->seq++;        else                proxy->priv->seq = 1;        /* Parse the actual XML message content */        doc = xmlParseMemory (msg->request_body->data,                              msg->request_body->length);        if (doc == NULL) {                /* Failed */                g_warning ("Failed to parse NOTIFY message body");                soup_message_set_status (msg,                                         SOUP_STATUS_INTERNAL_SERVER_ERROR);                return;        }        /* Get root propertyset element */        node = xmlDocGetRootElement (doc);        if (node == NULL || strcmp ((char *) node->name, "propertyset")) {                /* Empty or unsupported */                xmlFreeDoc (doc);                soup_message_set_status (msg, SOUP_STATUS_OK);                return;        }		/*	 * Some UPnP stacks (hello, myigd/1.0) block when sending a NOTIFY, so	 * call the callbacks in an idle handler so that if the client calls the	 * device in the notify callback the server can actually respond.	 */        proxy->priv->pending_notifies =

⌨️ 快捷键说明

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