/** * gssdp_resource_group_remove_resource: * @resource_group: A #GSSDPResourceGroup * @resource_id: The ID of the resource to remove * * Removes the resource with ID @resource_id from @resource_group. **/ void gssdp_resource_group_remove_resource (GSSDPResourceGroup *resource_group, guint resource_id) { GSSDPResourceGroupPrivate *priv; GList *l; g_return_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group)); g_return_if_fail (resource_id > 0); priv = gssdp_resource_group_get_instance_private (resource_group); for (l = priv->resources; l; l = l->next) { Resource *resource; resource = l->data; if (resource->id == resource_id) { priv->resources = g_list_remove (priv->resources, resource); resource_free (resource); return; } } }
/** * gssdp_resource_group_get_available: * @resource_group: A #GSSDPResourceGroup * * Return value: TRUE if @resource_group is available (advertised). **/ gboolean gssdp_resource_group_get_available (GSSDPResourceGroup *resource_group) { g_return_val_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group), FALSE); return resource_group->priv->available; }
/** * gssdp_resource_group_get_message_delay: * @resource_group: A #GSSDPResourceGroup * * Return value: the minimum time between each SSDP message in ms. **/ guint gssdp_resource_group_get_message_delay (GSSDPResourceGroup *resource_group) { g_return_val_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group), 0); return resource_group->priv->message_delay; }
/** * gssdp_resource_group_get_client: * @resource_group: A #GSSDPResourceGroup * * Returns: (transfer none): The #GSSDPClient @resource_group is associated with. **/ GSSDPClient * gssdp_resource_group_get_client (GSSDPResourceGroup *resource_group) { g_return_val_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group), NULL); return resource_group->priv->client; }
/** * gssdp_resource_group_remove_resource: * @resource_group: An @GSSDPResourceGroup * @resource_id: The ID of the resource to remove * * Removes the resource with ID @resource_id from @resource_group. **/ void gssdp_resource_group_remove_resource (GSSDPResourceGroup *resource_group, guint resource_id) { GList *l; g_return_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group)); g_return_if_fail (resource_id > 0); for (l = resource_group->priv->resources; l; l = l->next) { Resource *resource; resource = l->data; if (resource->id == resource_id) { resource_group->priv->resources = g_list_remove (resource_group->priv->resources, resource); resource_free (resource); return; } } }
/** * gssdp_resource_group_get_available: * @resource_group: A #GSSDPResourceGroup * * Return value: TRUE if @resource_group is available (advertised). **/ gboolean gssdp_resource_group_get_available (GSSDPResourceGroup *resource_group) { GSSDPResourceGroupPrivate *priv; g_return_val_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group), FALSE); priv = gssdp_resource_group_get_instance_private (resource_group); return priv->available; }
/** * gssdp_resource_group_get_message_delay: * @resource_group: A #GSSDPResourceGroup * * Return value: the minimum time between each SSDP message in ms. **/ guint gssdp_resource_group_get_message_delay (GSSDPResourceGroup *resource_group) { GSSDPResourceGroupPrivate *priv; g_return_val_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group), 0); priv = gssdp_resource_group_get_instance_private (resource_group); return priv->message_delay; }
/** * gssdp_resource_group_set_available: * @resource_group: A #GSSDPResourceGroup * @available: TRUE if @resource_group should be available (advertised) * * Sets @resource_group<!-- -->s availability to @available. Changing * @resource_group<!-- -->s availability causes it to announce its new state * to listening SSDP clients. **/ void gssdp_resource_group_set_available (GSSDPResourceGroup *resource_group, gboolean available) { g_return_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group)); if (resource_group->priv->available == available) return; resource_group->priv->available = available; if (available) { int timeout; /* We want to re-announce at least 3 times before the resource * group expires to cope with the unrelialble nature of UDP. * * Read the paragraphs about 'CACHE-CONTROL' on pages 21-22 of * UPnP Device Architecture Document v1.1 for further details. * */ timeout = resource_group->priv->max_age; if (G_LIKELY (timeout > 6)) timeout = (timeout / 3) - 1; /* Add re-announcement timer */ resource_group->priv->timeout_src = g_timeout_source_new_seconds (timeout); g_source_set_callback (resource_group->priv->timeout_src, resource_group_timeout, resource_group, NULL); g_source_attach (resource_group->priv->timeout_src, g_main_context_get_thread_default ()); g_source_unref (resource_group->priv->timeout_src); /* Make sure initial byebyes are sent grouped before initial * alives */ send_announcement_set (resource_group->priv->resources, (GFunc) send_initial_resource_byebye); send_announcement_set (resource_group->priv->resources, (GFunc) resource_alive); } else { /* Unannounce all resources */ send_announcement_set (resource_group->priv->resources, (GFunc) resource_byebye); /* Remove re-announcement timer */ g_source_destroy (resource_group->priv->timeout_src); resource_group->priv->timeout_src = NULL; } g_object_notify (G_OBJECT (resource_group), "available"); }
/** * gssdp_resource_group_get_client: * @resource_group: A #GSSDPResourceGroup * * Returns: (transfer none): The #GSSDPClient @resource_group is associated with. **/ GSSDPClient * gssdp_resource_group_get_client (GSSDPResourceGroup *resource_group) { GSSDPResourceGroupPrivate *priv; g_return_val_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group), NULL); priv = gssdp_resource_group_get_instance_private (resource_group); return priv->client; }
/** * gssdp_resource_group_set_message_delay: * @resource_group: A #GSSDPResourceGroup * @message_delay: The message delay in ms. * * Sets the minimum time between each SSDP message. **/ void gssdp_resource_group_set_message_delay (GSSDPResourceGroup *resource_group, guint message_delay) { g_return_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group)); if (resource_group->priv->message_delay == message_delay) return; resource_group->priv->message_delay = message_delay; g_object_notify (G_OBJECT (resource_group), "message-delay"); }
/** * gssdp_resource_group_set_max_age: * @resource_group: A #GSSDPResourceGroup * @max_age: The number of seconds advertisements are valid * * Sets the number of seconds advertisements are valid to @max_age. **/ void gssdp_resource_group_set_max_age (GSSDPResourceGroup *resource_group, guint max_age) { g_return_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group)); if (resource_group->priv->max_age == max_age) return; resource_group->priv->max_age = max_age; g_object_notify (G_OBJECT (resource_group), "max-age"); }
/** * gssdp_resource_group_set_message_delay: * @resource_group: A #GSSDPResourceGroup * @message_delay: The message delay in ms. * * Sets the minimum time between each SSDP message. **/ void gssdp_resource_group_set_message_delay (GSSDPResourceGroup *resource_group, guint message_delay) { GSSDPResourceGroupPrivate *priv; g_return_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group)); priv = gssdp_resource_group_get_instance_private (resource_group); if (priv->message_delay == message_delay) return; priv->message_delay = message_delay; g_object_notify (G_OBJECT (resource_group), "message-delay"); }
/** * gssdp_resource_group_set_max_age: * @resource_group: A #GSSDPResourceGroup * @max_age: The number of seconds advertisements are valid * * Sets the number of seconds advertisements are valid to @max_age. **/ void gssdp_resource_group_set_max_age (GSSDPResourceGroup *resource_group, guint max_age) { GSSDPResourceGroupPrivate *priv; g_return_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group)); priv = gssdp_resource_group_get_instance_private (resource_group); if (priv->max_age == max_age) return; priv->max_age = max_age; g_object_notify (G_OBJECT (resource_group), "max-age"); }
/* * Sets the #GSSDPClient @resource_group is associated with @client */ static void gssdp_resource_group_set_client (GSSDPResourceGroup *resource_group, GSSDPClient *client) { g_return_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group)); g_return_if_fail (GSSDP_IS_CLIENT (client)); resource_group->priv->client = g_object_ref (client); resource_group->priv->message_received_id = g_signal_connect_object (resource_group->priv->client, "message-received", G_CALLBACK (message_received_cb), resource_group, 0); g_object_notify (G_OBJECT (resource_group), "client"); }
/** * gssdp_resource_group_set_available: * @resource_group: A #GSSDPResourceGroup * @available: %TRUE if @resource_group should be available (advertised) * * Sets @resource_group<!-- -->s availability to @available. Changing * @resource_group<!-- -->s availability causes it to announce its new state * to listening SSDP clients. **/ void gssdp_resource_group_set_available (GSSDPResourceGroup *resource_group, gboolean available) { GSSDPResourceGroupPrivate *priv; g_return_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group)); priv = gssdp_resource_group_get_instance_private (resource_group); if (priv->available == available) return; priv->available = available; if (available) { setup_reannouncement_timeout (resource_group); /* Make sure initial byebyes are sent grouped before initial * alives */ send_announcement_set (priv->resources, (GFunc) send_initial_resource_byebye, NULL); send_announcement_set (priv->resources, (GFunc) resource_alive, NULL); } else { /* Unannounce all resources */ send_announcement_set (priv->resources, (GFunc) resource_byebye, NULL); /* Remove re-announcement timer */ g_source_destroy (priv->timeout_src); priv->timeout_src = NULL; } g_object_notify (G_OBJECT (resource_group), "available"); }
/** * gssdp_resource_group_update: * @resource_group: A #GSSDPResourceGroup * @new_boot_id: The new boot id of the device * * Send an ssdp::update message if the underlying #GSSDPClient is running * the UDA 1.1 protocol. Does nothing otherwise. */ void gssdp_resource_group_update (GSSDPResourceGroup *self, guint next_boot_id) { GSSDPUDAVersion version; GSSDPResourceGroupPrivate *priv; g_return_if_fail (GSSDP_IS_RESOURCE_GROUP (self)); g_return_if_fail (next_boot_id <= G_MAXINT32); priv = gssdp_resource_group_get_instance_private (self); version = gssdp_client_get_uda_version (priv->client); if (version == GSSDP_UDA_VERSION_1_0) return; if (!priv->available) { gssdp_client_set_boot_id (priv->client, next_boot_id); return; } /* Disable timeout */ g_clear_pointer (&priv->timeout_src, g_source_destroy); send_announcement_set (priv->resources, (GFunc) resource_update, GUINT_TO_POINTER (next_boot_id)); /* FIXME: This causes only the first of the three update messages to be correct. The other two will * have the new boot id as and boot id as the same value */ gssdp_client_set_boot_id (priv->client, next_boot_id); setup_reannouncement_timeout (self); send_announcement_set (priv->resources, (GFunc) resource_alive, NULL); }
/** * gssdp_resource_group_add_resource: * @resource_group: An @GSSDPResourceGroup * @target: The resource's target * @usn: The resource's USN * @locations: (element-type utf8): A #GList of the resource's locations * * Adds a resource with target @target, USN @usn, and locations @locations * to @resource_group. * * Return value: The ID of the added resource. **/ guint gssdp_resource_group_add_resource (GSSDPResourceGroup *resource_group, const char *target, const char *usn, GList *locations) { LOGD("gssdp_resource_group_add_resource"); LOGD("gssdp_resource_group_add_resource"); LOGD("gssdp_resource_group_add_resource"); Resource *resource; GList *l; GError *error; g_return_val_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group), 0); g_return_val_if_fail (target != NULL, 0); g_return_val_if_fail (usn != NULL, 0); g_return_val_if_fail (locations != NULL, 0); resource = g_slice_new0 (Resource); resource->resource_group = resource_group; resource->target = g_strdup (target); resource->usn = g_strdup (usn); error = NULL; resource->target_regex = create_target_regex (target, &resource->version, &error); if (error) { LOGD("Error compiling regular expression for '%s': %s", target, error->message); LOGD("Error compiling regular expression for '%s': %s", target, error->message); LOGD("Error compiling regular expression for '%s': %s", target, error->message); g_warning ("Error compiling regular expression for '%s': %s", target, error->message); g_error_free (error); resource_free (resource); return 0; } resource->initial_byebye_sent = FALSE; for (l = locations; l; l = l->next) { resource->locations = g_list_append (resource->locations, g_strdup (l->data)); } resource_group->priv->resources = g_list_prepend (resource_group->priv->resources, resource); resource->id = ++resource_group->priv->last_resource_id; if (resource_group->priv->available) resource_alive (resource); LOGD("g_list_prepend"); LOGD("g_list_prepend"); LOGD("g_list_prepend"); return resource->id; }
/** * gssdp_resource_group_add_resource: * @resource_group: A #GSSDPResourceGroup * @target: The resource's target * @usn: The resource's USN * @locations: (element-type utf8): A #GList of the resource's locations * * Adds a resource with target @target, USN @usn, and locations @locations * to @resource_group. * * Return value: The ID of the added resource. **/ guint gssdp_resource_group_add_resource (GSSDPResourceGroup *resource_group, const char *target, const char *usn, GList *locations) { GSSDPResourceGroupPrivate *priv = NULL; Resource *resource = NULL; GError *error = NULL; g_return_val_if_fail (GSSDP_IS_RESOURCE_GROUP (resource_group), 0); g_return_val_if_fail (target != NULL, 0); g_return_val_if_fail (usn != NULL, 0); g_return_val_if_fail (locations != NULL, 0); priv = gssdp_resource_group_get_instance_private (resource_group); resource = g_slice_new0 (Resource); resource->resource_group = resource_group; resource->target = g_strdup (target); resource->usn = g_strdup (usn); resource->target_regex = create_target_regex (target, &resource->version, &error); if (error) { g_warning ("Error compiling regular expression for '%s': %s", target, error->message); g_error_free (error); resource_free (resource); return 0; } resource->initial_byebye_sent = FALSE; resource->locations = g_list_copy_deep (locations, (GCopyFunc) g_strdup, NULL); priv->resources = g_list_prepend (priv->resources, resource); resource->id = ++priv->last_resource_id; if (priv->available) resource_alive (resource); return resource->id; }