コード例 #1
0
static void
gssdp_resource_group_set_property (GObject      *object,
                                   guint         property_id,
                                   const GValue *value,
                                   GParamSpec   *pspec)
{
        GSSDPResourceGroup *resource_group;

        resource_group = GSSDP_RESOURCE_GROUP (object);

        switch (property_id) {
        case PROP_CLIENT:
                gssdp_resource_group_set_client (resource_group,
                                                 g_value_get_object (value));
                break;
        case PROP_MAX_AGE:
                gssdp_resource_group_set_max_age (resource_group,
                                                  g_value_get_long (value));
                break;
        case PROP_AVAILABLE:
                gssdp_resource_group_set_available
                        (resource_group, g_value_get_boolean (value));
                break;
        case PROP_MESSAGE_DELAY:
                gssdp_resource_group_set_message_delay
                        (resource_group, g_value_get_uint (value));
                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
                break;
        }
}
コード例 #2
0
/*
 * Send the next queued message, if any
 */
static gboolean
process_queue (gpointer data)
{
        GSSDPResourceGroup *resource_group;

        resource_group = GSSDP_RESOURCE_GROUP (data);

        if (g_queue_is_empty (resource_group->priv->message_queue)) {
                /* this is the timeout after last message in queue */
                resource_group->priv->message_src = NULL;

                return FALSE;
        } else {
                GSSDPClient *client;
                char *message;

                client = resource_group->priv->client;
                message = g_queue_pop_head
                        (resource_group->priv->message_queue);

                _gssdp_client_send_message (client,
                                            NULL,
                                            0,
                                            message,
                                            _GSSDP_DISCOVERY_RESPONSE);
                g_free (message);

                return TRUE;
        }
}
コード例 #3
0
static void
gssdp_resource_group_dispose (GObject *object)
{
        GSSDPResourceGroup *resource_group;
        GSSDPResourceGroupPrivate *priv;

        resource_group = GSSDP_RESOURCE_GROUP (object);
        priv = resource_group->priv;

        while (priv->resources) {
                resource_free (priv->resources->data);
                priv->resources =
                        g_list_delete_link (priv->resources,
                                            priv->resources);
        }

        if (priv->message_queue) {
                /* send messages without usual delay */
                while (!g_queue_is_empty (priv->message_queue)) {
                        if (priv->available)
                                process_queue (resource_group);
                        else
                                g_free (g_queue_pop_head
                                        (priv->message_queue));
                }

                g_queue_free (priv->message_queue);
                priv->message_queue = NULL;
        }

        if (priv->message_src) {
                g_source_destroy (priv->message_src);
                priv->message_src = NULL;
        }

        if (priv->timeout_src) {
                g_source_destroy (priv->timeout_src);
                priv->timeout_src = NULL;
        }

        if (priv->client) {
                if (g_signal_handler_is_connected
                        (priv->client,
                         priv->message_received_id)) {
                        g_signal_handler_disconnect
                                (priv->client,
                                 priv->message_received_id);
                }

                g_object_unref (priv->client);
                priv->client = NULL;
        }

        G_OBJECT_CLASS (gssdp_resource_group_parent_class)->dispose (object);
}
コード例 #4
0
/*
 * Called to re-announce all resources periodically
 */
static gboolean
resource_group_timeout (gpointer user_data)
{
        GSSDPResourceGroup *resource_group;

        resource_group = GSSDP_RESOURCE_GROUP (user_data);

        send_announcement_set (resource_group->priv->resources,
                               (GFunc) resource_alive);

        return TRUE;
}
コード例 #5
0
ファイル: gssdp-resource-group.c プロジェクト: GNOME/gssdp
/*
 * Called to re-announce all resources periodically
 */
static gboolean
resource_group_timeout (gpointer user_data)
{
        GSSDPResourceGroup *resource_group;
        GSSDPResourceGroupPrivate *priv;

        resource_group = GSSDP_RESOURCE_GROUP (user_data);
        priv = gssdp_resource_group_get_instance_private (resource_group);

        send_announcement_set (priv->resources, (GFunc) resource_alive, NULL);

        return TRUE;
}
コード例 #6
0
ファイル: gssdp-resource-group.c プロジェクト: GNOME/gssdp
static void
gssdp_resource_group_dispose (GObject *object)
{
        GSSDPResourceGroup *resource_group;
        GSSDPResourceGroupPrivate *priv;

        resource_group = GSSDP_RESOURCE_GROUP (object);
        priv = gssdp_resource_group_get_instance_private (resource_group);

        g_list_free_full (priv->resources, (GFreeFunc) resource_free);
        priv->resources = NULL;

        if (priv->message_queue) {
                /* send messages without usual delay */
                while (!g_queue_is_empty (priv->message_queue)) {
                        if (priv->available)
                                process_queue (resource_group);
                        else
                                g_free (g_queue_pop_head
                                        (priv->message_queue));
                }

                g_clear_pointer (&priv->message_queue, g_queue_free);
        }


        /* No need to unref sources, already done on creation */
        g_clear_pointer (&priv->message_src, g_source_destroy);
        g_clear_pointer (&priv->timeout_src, g_source_destroy);

        if (priv->client) {
                if (g_signal_handler_is_connected
                        (priv->client,
                         priv->message_received_id)) {
                        g_signal_handler_disconnect
                                (priv->client,
                                 priv->message_received_id);
                }

                g_clear_object (&priv->client);
        }

        G_OBJECT_CLASS (gssdp_resource_group_parent_class)->dispose (object);
}
コード例 #7
0
/*
 * Received a message
 */
static void
message_received_cb (GSSDPClient        *client,
                     const char         *from_ip,
                     gushort             from_port,
                     _GSSDPMessageType   type,
                     SoupMessageHeaders *headers,
                     gpointer            user_data)
{
        GSSDPResourceGroup *resource_group;
        const char *target, *mx_str, *version_str, *man;
        gboolean want_all;
        int mx, version;
        GList *l;

        resource_group = GSSDP_RESOURCE_GROUP (user_data);

        /* Only process if we are available */
        if (!resource_group->priv->available)
                return;

        /* We only handle discovery requests */
        if (type != _GSSDP_DISCOVERY_REQUEST)
                return;

        /* Extract target */
        target = soup_message_headers_get_one (headers, "ST");
        if (!target) {
                g_warning ("Discovery request did not have an ST header");

                return;
        }

        /* Is this the "ssdp:all" target? */
        want_all = (strcmp (target, GSSDP_ALL_RESOURCES) == 0);

        /* Extract MX */
        mx_str = soup_message_headers_get_one (headers, "MX");
        if (!mx_str || atoi (mx_str) <= 0) {
                g_warning ("Discovery request did not have a valid MX header");

                return;
        }

        man = soup_message_headers_get_one (headers, "MAN");
        if (!man) {
                g_warning ("Discovery request did not have a valid MAN header");

                return;
        }

        mx = atoi (mx_str);

        /* Extract version */
        version_str = get_version_for_target ((char *) target);
        if (version_str != NULL)
                version = atoi (version_str);
        else
                version = 0;

        /* Find matching resource */
        for (l = resource_group->priv->resources; l; l = l->next) {
                Resource *resource;

                resource = l->data;

                if (want_all ||
                    (g_regex_match (resource->target_regex,
                                    target,
                                    0,
                                    NULL) &&
                     version <= resource->version)) {
                        /* Match. */
                        guint timeout;
                        DiscoveryResponse *response;

                        /* Get a random timeout from the interval [0, mx] */
                        timeout = g_random_int_range (0, mx * 1000);

                        /* Prepare response */
                        response = g_slice_new (DiscoveryResponse);

                        response->dest_ip   = g_strdup (from_ip);
                        response->dest_port = from_port;
                        response->resource  = resource;

                        if (want_all)
                                response->target = g_strdup (resource->target);
                        else
                                response->target = g_strdup (target);

                        /* Add timeout */
                        response->timeout_src = g_timeout_source_new (timeout);
                        g_source_set_callback (response->timeout_src,
                                               discovery_response_timeout,
                                               response, NULL);

                        g_source_attach (response->timeout_src,
                                         g_main_context_get_thread_default ());

                        g_source_unref (response->timeout_src);

                        /* Add to resource */
                        resource->responses =
                                g_list_prepend (resource->responses, response);
                }
        }
}