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); }
/* * 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"); }
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); }
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; }
/** * 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); } }