Beispiel #1
0
static void
cancellable_cancelled_cb (GCancellable *cancellable,
                          gpointer user_data)
{
        GUPnPServiceInfo *info;
        GetSCPDURLData *data;
        SoupSession *session;
        GError *error;

        data = user_data;
        info = data->info;

        session = gupnp_context_get_session (info->priv->context);
        soup_session_cancel_message (session,
                                     data->message,
                                     SOUP_STATUS_CANCELLED);

        info->priv->pending_gets =
                g_list_remove (info->priv->pending_gets, data);

        error = g_error_new (G_IO_ERROR,
                             G_IO_ERROR_CANCELLED,
                             "The call was canceled");

        data->callback (data->info,
                        NULL,
                        error,
                        data->user_data);

        get_scpd_url_data_free (data);
}
Beispiel #2
0
/*
 * Downloads and parses (or takes from cache) @description_url,
 * creating:
 *  - A #GUPnPDeviceProxy for the device specified by @udn if @service_type
 *    is %NULL.
 *  - A #GUPnPServiceProxy for the service of type @service_type from the device
 *    specified by @udn if @service_type is not %NULL.
 */
static void
load_description (GUPnPControlPoint *control_point,
                  const char        *description_url,
                  const char        *udn,
                  const char        *service_type)
{
        GUPnPXMLDoc *doc;

        doc = g_hash_table_lookup (control_point->priv->doc_cache,
                                   description_url);
        if (doc) {
                /* Doc was cached */
                description_loaded (control_point,
                                    doc,
                                    udn,
                                    service_type,
                                    description_url);
        } else {
                /* Asynchronously download doc */
                GUPnPContext *context;
                SoupSession *session;
                GetDescriptionURLData *data;

                context = gupnp_control_point_get_context (control_point);

                session = gupnp_context_get_session (context);

                data = g_slice_new (GetDescriptionURLData);

                data->message = soup_message_new (SOUP_METHOD_GET,
                                                  description_url);
                if (data->message == NULL) {
                        g_warning ("Invalid description URL: %s",
                                   description_url);

                        g_slice_free (GetDescriptionURLData, data);

                        return;
                }

                http_request_set_user_agent (data->message);
                http_request_set_accept_language (data->message);

                data->control_point   = control_point;

                data->udn             = g_strdup (udn);
                data->service_type    = g_strdup (service_type);
                data->description_url = g_strdup (description_url);

                control_point->priv->pending_gets =
                        g_list_prepend (control_point->priv->pending_gets,
                                        data);

	        soup_session_queue_message (session,
                                            data->message,
                                            (SoupSessionCallback)
                                                   got_description_url,
                                            data);
        }
}
/**
 * gupnp_service_info_get_introspection_async
 * @info: A #GUPnPServiceInfo
 * @callback: callback to be called when introspection object is ready.
 * @user_data: user_data to be passed to the callback.
 *
 * Note that introspection object is created from the information in service
 * description document (SCPD) provided by the service so it can not be created
 * if the service does not provide an SCPD.
 **/
void
gupnp_service_info_get_introspection_async
                                (GUPnPServiceInfo                 *info,
                                 GUPnPServiceIntrospectionCallback callback,
                                 gpointer                          user_data)
{
        GetSCPDURLData *data;
        char *scpd_url;
        SoupSession *session;

        g_return_if_fail (GUPNP_IS_SERVICE_INFO (info));
        g_return_if_fail (callback != NULL);

        data = g_slice_new (GetSCPDURLData);

        scpd_url = gupnp_service_info_get_scpd_url (info);

        data->message = NULL;
        if (scpd_url != NULL) {
                data->message = soup_message_new (SOUP_METHOD_GET, scpd_url);

                g_free (scpd_url);
        }

        if (data->message == NULL) {
                GError *error;

                error = g_error_new
                                (GUPNP_SERVER_ERROR,
                                 GUPNP_SERVER_ERROR_INVALID_URL,
                                 "No valid SCPD URL defined");

                callback (info, NULL, error, user_data);

                g_error_free (error);

                g_slice_free (GetSCPDURLData, data);

                return;
        }

        data->info      = info;
        data->callback  = callback;
        data->user_data = user_data;

        /* Send off the message */
        info->priv->pending_gets =
                g_list_prepend (info->priv->pending_gets,
                                data);

        session = gupnp_context_get_session (info->priv->context);

        soup_session_queue_message (session,
                                    data->message,
                                    (SoupSessionCallback) got_scpd_url,
                                    data);
}
static void
_context_available (GUPnPContextManager *manager, GUPnPContext *gupnp_context,
                    GUPnPSimpleIgd *self)
{
    SoupSession *session;

    session = gupnp_context_get_session (gupnp_context);
    g_object_set (session, "timeout", SOUP_REQUEST_TIMEOUT, NULL);

    gupnp_simple_igd_add_control_point (self, gupnp_context,
                                        "urn:schemas-upnp-org:service:WANIPConnection:1");
    gupnp_simple_igd_add_control_point (self, gupnp_context,
                                        "urn:schemas-upnp-org:service:WANPPPConnection:1");
}
Beispiel #5
0
static void
gupnp_service_info_dispose (GObject *object)
{
        GUPnPServiceInfo *info;
        GUPnPServiceInfoPrivate *priv;

        info = GUPNP_SERVICE_INFO (object);
        priv = gupnp_service_info_get_instance_private (info);

        /* Cancel any pending SCPD GETs */
        if (priv->context) {
                SoupSession *session;

                session = gupnp_context_get_session (priv->context);

                while (priv->pending_gets) {
                        GetSCPDURLData *data;

                        data = priv->pending_gets->data;

                        if (data->cancellable)
                                g_cancellable_disconnect (data->cancellable,
                                                          data->cancelled_id);

                        soup_session_cancel_message (session,
                                                     data->message,
                                                     SOUP_STATUS_CANCELLED);

                        get_scpd_url_data_free (data);

                        priv->pending_gets =
                                g_list_delete_link (priv->pending_gets,
                                                    priv->pending_gets);
                }

                /* Unref context */
                g_object_unref (priv->context);
                priv->context = NULL;
        }

        if (priv->doc) {
                g_object_unref (priv->doc);
                priv->doc = NULL;
        }

        G_OBJECT_CLASS (gupnp_service_info_parent_class)->dispose (object);
}
Beispiel #6
0
static void
gupnp_control_point_dispose (GObject *object)
{
        GUPnPControlPoint *control_point;
        GSSDPResourceBrowser *browser;
        GObjectClass *object_class;

        control_point = GUPNP_CONTROL_POINT (object);
        browser = GSSDP_RESOURCE_BROWSER (control_point);

        gssdp_resource_browser_set_active (browser, FALSE);

        if (control_point->priv->factory) {
                g_object_unref (control_point->priv->factory);
                control_point->priv->factory = NULL;
        }

        /* Cancel any pending description file GETs */
        while (control_point->priv->pending_gets) {
                GetDescriptionURLData *data;
                GUPnPContext *context;
                SoupSession *session;

                data = control_point->priv->pending_gets->data;

                context = gupnp_control_point_get_context (control_point);
                session = gupnp_context_get_session (context);

                soup_session_cancel_message (session,
                                             data->message,
                                             SOUP_STATUS_CANCELLED);

                get_description_url_data_free (data);
        }

        /* Release weak references on remaining cached documents */
        g_hash_table_foreach (control_point->priv->doc_cache,
                              weak_unref_doc,
                              control_point);

        /* Call super */
        object_class = G_OBJECT_CLASS (gupnp_control_point_parent_class);
        object_class->dispose (object);
}
/**
 * gupnp_service_info_get_introspection
 * @info: A #GUPnPServiceInfo
 * @error: return location for a #GError, or %NULL
 *
 * Note that introspection object is created from the information in service
 * description document (SCPD) provided by the service so it can not be created
 * if the service does not provide an SCPD.
 *
 * Warning: You  should use gupnp_service_info_get_introspection_async()
 * instead, this function re-enter the GMainloop before returning.
 *
 * Return value: (transfer full):  A new #GUPnPServiceIntrospection for this
 * service or %NULL. Unref after use.
 **/
GUPnPServiceIntrospection *
gupnp_service_info_get_introspection (GUPnPServiceInfo *info,
                                      GError          **error)
{
        GUPnPServiceIntrospection *introspection;
        SoupSession *session;
        SoupMessage *msg;
        int status;
        char *scpd_url;
        xmlDoc *scpd;

        g_return_val_if_fail (GUPNP_IS_SERVICE_INFO (info), NULL);

        introspection = NULL;

        scpd_url = gupnp_service_info_get_scpd_url (info);

        msg = NULL;
        if (scpd_url != NULL) {
                msg = soup_message_new (SOUP_METHOD_GET, scpd_url);

                g_free (scpd_url);
        }

        if (msg == NULL) {
                g_set_error (error,
                             GUPNP_SERVER_ERROR,
                             GUPNP_SERVER_ERROR_INVALID_URL,
                             "No valid SCPD URL defined");

                return NULL;
        }

        /* Send off the message */
        session = gupnp_context_get_session (info->priv->context);

        status = soup_session_send_message (session, msg);
        if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
                _gupnp_error_set_server_error (error, msg);

                g_object_unref (msg);

                return NULL;
        }

        scpd = xmlRecoverMemory (msg->response_body->data,
                                 msg->response_body->length);

        g_object_unref (msg);

        if (scpd) {
                introspection = gupnp_service_introspection_new (scpd);

                xmlFreeDoc (scpd);
        }

        if (!introspection) {
                g_set_error (error,
                             GUPNP_SERVER_ERROR,
                             GUPNP_SERVER_ERROR_INVALID_RESPONSE,
                             "Could not parse SCPD");
        }

        return introspection;
}
Beispiel #8
0
/**
 * gupnp_service_info_get_introspection_async_full:
 * @info: A #GUPnPServiceInfo
 * @callback: (scope async) : callback to be called when introspection object is ready.
 * @cancellable: GCancellable that can be used to cancel the call, or %NULL.
 * @user_data: user_data to be passed to the callback.
 *
 * Note that introspection object is created from the information in service
 * description document (SCPD) provided by the service so it can not be created
 * if the service does not provide an SCPD.
 *
 * If @cancellable is used to cancel the call, @callback will be called with
 * error code %G_IO_ERROR_CANCELLED.
 *
 * Since: 0.20.9
 **/
void
gupnp_service_info_get_introspection_async_full
                                (GUPnPServiceInfo                 *info,
                                 GUPnPServiceIntrospectionCallback callback,
                                 GCancellable                     *cancellable,
                                 gpointer                          user_data)
{
        GetSCPDURLData *data;
        char *scpd_url;
        SoupSession *session;
        GUPnPServiceInfoPrivate *priv;

        g_return_if_fail (GUPNP_IS_SERVICE_INFO (info));
        g_return_if_fail (callback != NULL);

        data = g_slice_new (GetSCPDURLData);

        scpd_url = gupnp_service_info_get_scpd_url (info);

        data->message = NULL;
        if (scpd_url != NULL) {
                GUPnPContext *context = NULL;
                char *local_scpd_url = NULL;

                context = gupnp_service_info_get_context (info);

                local_scpd_url = gupnp_context_rewrite_uri (context, scpd_url);
                g_free (scpd_url);

                data->message = soup_message_new (SOUP_METHOD_GET,
                                                  local_scpd_url);
                g_free (local_scpd_url);
        }

        if (data->message == NULL) {
                GError *error;

                error = g_error_new
                                (GUPNP_SERVER_ERROR,
                                 GUPNP_SERVER_ERROR_INVALID_URL,
                                 "No valid SCPD URL defined");

                callback (info, NULL, error, user_data);

                g_error_free (error);

                g_slice_free (GetSCPDURLData, data);

                return;
        }

        data->info      = info;
        data->callback  = callback;
        data->user_data = user_data;

        /* Send off the message */
        priv = gupnp_service_info_get_instance_private (info);
        priv->pending_gets = g_list_prepend (priv->pending_gets, data);

        session = gupnp_context_get_session (priv->context);

        soup_session_queue_message (session,
                                    data->message,
                                    (SoupSessionCallback) got_scpd_url,
                                    data);

        data->cancellable = cancellable;
        if (data->cancellable) {
                g_object_ref (cancellable);
                data->cancelled_id = g_cancellable_connect
                                (data->cancellable,
                                 G_CALLBACK (cancellable_cancelled_cb),
                                 data,
                                 NULL);
        }
}