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

📄 gupnp-service.c

📁 另一 UPNP SDK 支持在UNIX/LINUX上运行。 UPnP是一种网络协议
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Unsubscription request */static voidunsubscribe (GUPnPService *service,             SoupMessage  *msg,             const char   *sid){        if (g_hash_table_remove (service->priv->subscriptions, sid))                soup_message_set_status (msg, SOUP_STATUS_OK);        else                soup_message_set_status (msg, SOUP_STATUS_PRECONDITION_FAILED);}/* eventSubscriptionURL handler */static voidsubscription_server_handler (SoupServer        *soup_server,                             SoupMessage       *msg,                              const char        *server_path,                             GHashTable        *query,                             SoupClientContext *soup_client,                             gpointer           user_data){        GUPnPService *service;        const char *callback, *nt, *timeout, *sid;        service = GUPNP_SERVICE (user_data);        callback = soup_message_headers_get (msg->request_headers, "Callback");        nt       = soup_message_headers_get (msg->request_headers, "NT");        timeout  = soup_message_headers_get (msg->request_headers, "Timeout");        sid      = soup_message_headers_get (msg->request_headers, "SID");        /* Choose appropriate handler */        if (strcmp (msg->method, GENA_METHOD_SUBSCRIBE) == 0) {                if (callback) {                        if (sid) {                                soup_message_set_status                                        (msg, SOUP_STATUS_BAD_REQUEST);                        } else if (!nt || strcmp (nt, "upnp:event") != 0) {                                soup_message_set_status                                        (msg, SOUP_STATUS_PRECONDITION_FAILED);                        } else {                                subscribe (service, msg, callback, timeout);                        }                } else if (sid) {                        if (nt) {                                soup_message_set_status                                        (msg, SOUP_STATUS_BAD_REQUEST);                        } else {                                resubscribe (service, msg, sid, timeout);                        }                } else {                        soup_message_set_status                                (msg, SOUP_STATUS_BAD_REQUEST);                }        } else if (strcmp (msg->method, GENA_METHOD_UNSUBSCRIBE) == 0) {                if (sid) {                        if (nt || callback) {                                soup_message_set_status                                        (msg, SOUP_STATUS_BAD_REQUEST);                        } else {                                unsubscribe (service, msg, sid);                        }                } else {                        soup_message_set_status                                (msg, SOUP_STATUS_PRECONDITION_FAILED);                }        } else {                soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);        }}static GObject *gupnp_service_constructor (GType                  type,                           guint                  n_construct_params,                           GObjectConstructParam *construct_params){        GObjectClass *object_class;        GObject *object;        GUPnPService *service;        GUPnPServiceInfo *info;        GError *error;        GUPnPServiceIntrospection *introspection;        const GList *state_variables, *l;        GUPnPContext *context;        SoupServer *server;        SoupURI *uri;        char *url;        object_class = G_OBJECT_CLASS (gupnp_service_parent_class);        /* Construct */        object = object_class->constructor (type,                                            n_construct_params,                                            construct_params);        service = GUPNP_SERVICE (object);        info    = GUPNP_SERVICE_INFO (object);        /* Get introspection and save state variable names */        error = NULL;        introspection = gupnp_service_info_get_introspection (info, &error);        if (introspection) {                state_variables =                        gupnp_service_introspection_list_state_variables                                                                (introspection);                for (l = state_variables; l; l = l->next) {                        GUPnPServiceStateVariableInfo *variable;                        variable = l->data;                        if (!variable->send_events)                                continue;                        service->priv->state_variables =                                g_list_prepend (service->priv->state_variables,                                                g_strdup (variable->name));                }                g_object_unref (introspection);        } else {                g_warning ("Failed to get SCPD: %s\n"                           "The initial event message will not be sent.",                           error->message);                g_error_free (error);        }        /* Get server */        context = gupnp_service_info_get_context (info);        server = gupnp_context_get_server (context);        /* Run listener on controlURL */        url = gupnp_service_info_get_control_url (info);        uri = soup_uri_new (url);        g_free (url);        url = soup_uri_to_string (uri, TRUE);        soup_uri_free (uri);        soup_server_add_handler (server, url,                                 control_server_handler, object, NULL);        g_free (url);        /* Run listener on eventSubscriptionURL */        url = gupnp_service_info_get_event_subscription_url (info);        uri = soup_uri_new (url);        g_free (url);        url = soup_uri_to_string (uri, TRUE);        soup_uri_free (uri);        soup_server_add_handler (server, url,                                 subscription_server_handler, object, NULL);        g_free (url);        return object;}static gbooleansay_yes (gpointer key,         gpointer value,         gpointer user_data){        return TRUE;}/* Root device availability changed. */static voidnotify_available_cb (GObject *object,                     GParamSpec *pspec,                     gpointer    user_data){        GUPnPService *service;        service = GUPNP_SERVICE (user_data);        if (!gupnp_root_device_get_available (GUPNP_ROOT_DEVICE (object))) {                /* Root device now unavailable: Purge subscriptions */                g_hash_table_foreach_remove (service->priv->subscriptions,                                             say_yes,                                             NULL);        }}static voidgupnp_service_set_property (GObject      *object,                            guint         property_id,                            const GValue *value,                            GParamSpec   *pspec){        GUPnPService *service;        service = GUPNP_SERVICE (object);        switch (property_id) {        case PROP_ROOT_DEVICE:                service->priv->root_device =                        g_object_ref (g_value_get_object (value));                service->priv->notify_available_id =                        g_signal_connect_object (service->priv->root_device,                                                 "notify::available",                                                 G_CALLBACK                                                        (notify_available_cb),                                                 object,                                                 0);                break;        default:                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);                break;        }}static voidgupnp_service_get_property (GObject    *object,                            guint       property_id,                            GValue     *value,                            GParamSpec *pspec){        GUPnPService *service;        service = GUPNP_SERVICE (object);        switch (property_id) {        case PROP_ROOT_DEVICE:                g_value_set_object (value, service->priv->root_device);                break;        default:                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);                break;        }}static voidgupnp_service_dispose (GObject *object){        GUPnPService *service;        GObjectClass *object_class;        service = GUPNP_SERVICE (object);        if (service->priv->root_device) {                if (g_signal_handler_is_connected                        (service->priv->root_device,                         service->priv->notify_available_id)) {                        g_signal_handler_disconnect                                (service->priv->root_device,                                 service->priv->notify_available_id);                }                g_object_unref (service->priv->root_device);                service->priv->root_device = NULL;        }        /* Cancel pending messages */        g_hash_table_remove_all (service->priv->subscriptions);        /* Call super */        object_class = G_OBJECT_CLASS (gupnp_service_parent_class);        object_class->dispose (object);}static voidgupnp_service_finalize (GObject *object){        GUPnPService *service;        GObjectClass *object_class;        NotifyData *data;        service = GUPNP_SERVICE (object);        /* Free subscription hash */        g_hash_table_destroy (service->priv->subscriptions);        /* Free state variable list */        while (service->priv->state_variables) {                g_free (service->priv->state_variables->data);                service->priv->state_variables =                        g_list_delete_link (service->priv->state_variables,                                            service->priv->state_variables);        }        /* Free notify queue */        while ((data = g_queue_pop_head (service->priv->notify_queue)))                notify_data_free (data);        g_queue_free (service->priv->notify_queue);        /* Call super */        object_class = G_OBJECT_CLASS (gupnp_service_parent_class);        object_class->finalize (object);}static voidgupnp_service_class_init (GUPnPServiceClass *klass){        GObjectClass *object_class;        GUPnPServiceInfoClass *info_class;        object_class = G_OBJECT_CLASS (klass);        object_class->set_property = gupnp_service_set_property;        object_class->get_property = gupnp_service_get_property;        object_class->constructor  = gupnp_service_constructor;        object_class->dispose      = gupnp_service_dispose;        object_class->finalize     = gupnp_service_finalize;        info_class = GUPNP_SERVICE_INFO_CLASS (klass);        g_type_class_add_private (klass, sizeof (GUPnPServicePrivate));        /**         * GUPnPService:root-device         *         * The containing #GUPnPRootDevice.         **/        g_object_class_install_property                (object_class,                 PROP_ROOT_DEVICE,                 g_param_spec_object ("root-device",                                      "Root device",                                      "The GUPnPRootDevice",                                      GUPNP_TYPE_ROOT_DEVICE,                                      G_PARAM_READWRITE |                                      G_PARAM_CONSTRUCT_ONLY |                                      G_PARAM_STATIC_NAME |                                      G_PARAM_STATIC_NICK |                                      G_PARAM_STATIC_BLURB));        /**         * GUPnPService::action-invoked         * @service: The #GUPnPService that received the signal         * @action: The invoked #GUPnPAction         *         * Emitted whenever an action is invoked. Handler should process         * @action.         **/        signals[ACTION_INVOKED] =                g_signal_new ("action-invoked",                              GUPNP_TYPE_SERVICE,                              G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,                              G_STRUCT_OFFSET (GUPnPServiceClass,                                               action_invoked),                              NULL,                              NULL,                              g_cclosure_marshal_VOID__POINTER,                              G_TYPE_NONE,                              1,                              GUPNP_TYPE_SERVICE_ACTION);        /**         * GUPnPService::query-variable         * @service: The #GUPnPService that received the signal         * @variable: The variable that is being queried         * @value: The location of the #GValue of the variable         *         * Emitted whenever @service needs to know the value of @variable.         * Handler should fill @value with the value of @variable.         **/        signals[QUERY_VARIABLE] =                g_signal_new ("query-variable",                              GUPNP_TYPE_SERVICE,                              G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,                              G_STRUCT_OFFSET (GUPnPServiceClass,                                               query_variable),                              NULL,                              NULL,                              gupnp_marshal_VOID__STRING_POINTER,                              G_TYPE_NONE,                              2,                              G_TYPE_STRING,                              G_TYPE_POINTER /* Not G_TYPE_VALUE as this                                                is an outward argument! */);        /**         * GUPnPService::notify-failed         * @service: The #GUPnPService that received the signal         * @callback_url: The callback URL         * @reason: A pointer to a #GError describing why the notify failed         *         * Emitted whenever notification of a client fails.         **/        signals[NOTIFY_FAILED] =                g_signal_new ("notify-failed",                              GUPNP_TYPE_SERVICE,                              G_SIGNAL_RUN_LAST,                              G_STRUCT_OFFSET (GUPnPServiceClass,                                               notify_failed),                              NULL,                              NULL,                              gupnp_marshal_VOID__POINTER_POINTER,                              G_TYPE_NONE,                              2,                              G_TYPE_POINTER,                              G_TYPE_POINTER);}/** * gupnp_service_notify * @service: A #GUPnPService * @Varargs: Tuples of variable name, variable type, and variable value, * terminated with %NULL. * * Notifies listening clients that the properties listed in @Varargs * have changed to the specified values. **/voidgupnp_service_notify (GUPnPService *service,                      ...){        va_list var_args;        g_return_if_fail (GUPNP_IS_SERVICE (service));        va_start (var_args, service);        gupnp_service_notify_valist (service, var_args);        va_end (var_args);}/** * gupnp_service_notify_valist * @service: A #GUPnPService * @var_args: A va_list of tuples of variable name, variable type, and variable * value, terminated with %NULL. * * See gupnp_service_notify(); this version takes a va_list for * use by language bindings. **/voidgupnp_service_notify_valist (GUPnPService *service,                             va_list       var_args){        const char *var_name;        GType var_type;        GValue value = {0, };        char *collect_error;        g_return_if_fail (GUPNP_IS_SERVICE (service));        collect_error = NULL;        var_name = va_arg (var_args, const char *);        while (var_name) {                var_type = va_arg (var_args, GType);                g_value_init (&value, var_type);                G_VALUE_COLLECT (&value, var_args, 0, &collect_error);                if (!collect_error) {                        gupnp_service_notify_value (service, var_name, &value);                        g_value_unset (&value);

⌨️ 快捷键说明

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