From bd07f71438601715b54a4af102315d8d459b2668 Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Mon, 18 Feb 2013 16:55:37 +0100 Subject: [PATCH] Add a function doing a service rescan. It simply starts a discovery, but now discovery was modified a bit, so every service that has replied to our discovery messages is put into map with responsive services. After a reasonable amount of time (here: 5 seconds), it looks for services that were cached, but haven't yet responded. Such services are removed from cache with notifying about them being unavailable beforehand. This was added so we can do a rescan for services that do not send an announcement messages when they appear or such messages may get lost in network. --- doc/gssdp-sections.txt | 1 + libgssdp/gssdp-resource-browser.c | 105 ++++++++++++++++++++++++++++++++++++++ libgssdp/gssdp-resource-browser.h | 3 ++ 3 files changed, 109 insertions(+) diff --git a/doc/gssdp-sections.txt b/doc/gssdp-sections.txt index 7b73261..4f4361f 100644 --- a/doc/gssdp-sections.txt +++ b/doc/gssdp-sections.txt @@ -63,6 +63,7 @@ gssdp_resource_browser_set_mx gssdp_resource_browser_get_mx gssdp_resource_browser_set_active gssdp_resource_browser_get_active +gssdp_resource_browser_rescan GSSDP_RESOURCE_BROWSER GSSDP_IS_RESOURCE_BROWSER diff --git a/libgssdp/gssdp-resource-browser.c b/libgssdp/gssdp-resource-browser.c index c8208fe..04b23fe 100644 --- a/libgssdp/gssdp-resource-browser.c +++ b/libgssdp/gssdp-resource-browser.c @@ -41,6 +41,7 @@ #include "gssdp-protocol.h" #include "gssdp-marshal.h" +#define RESCAN_TIMEOUT 5 /* 5 seconds */ #define MAX_DISCOVERY_MESSAGES 3 #define DISCOVERY_FREQUENCY 500 /* 500 ms */ @@ -65,6 +66,9 @@ struct _GSSDPResourceBrowserPrivate { GSource *timeout_src; guint num_discovery; guint version; + + GSource *refresh_cache_src; + GHashTable *fresh_resources; }; enum { @@ -112,6 +116,8 @@ static void start_discovery (GSSDPResourceBrowser *resource_browser); static void stop_discovery (GSSDPResourceBrowser *resource_browser); +static gboolean +refresh_cache (gpointer data); static void gssdp_resource_browser_init (GSSDPResourceBrowser *resource_browser) @@ -582,6 +588,30 @@ gssdp_resource_browser_get_active (GSSDPResourceBrowser *resource_browser) return resource_browser->priv->active; } +/** + * gssdp_resource_browser_rescan: + * @resource_browser: A #GSSDPResourceBrowser + * + * Begins discovery if @resource_browser is active and no discovery is + * performed. Otherwise does nothing. + * + * Return value: %TRUE if rescaning has been started. + **/ +gboolean +gssdp_resource_browser_rescan (GSSDPResourceBrowser *resource_browser) +{ + g_return_val_if_fail (GSSDP_IS_RESOURCE_BROWSER (resource_browser), 0); + + if (resource_browser->priv->active && + resource_browser->priv->timeout_src == NULL && + resource_browser->priv->refresh_cache_src == NULL) { + start_discovery (resource_browser); + return TRUE; + } + + return FALSE; +} + /* * Resource expired: Remove */ @@ -652,6 +682,16 @@ resource_available (GSSDPResourceBrowser *resource_browser, /* Get from cache, if possible */ resource = g_hash_table_lookup (resource_browser->priv->resources, canonical_usn); + /* Put usn into fresh resources, so this resource will not be + * removed on cache refreshing. */ + if (resource_browser->priv->fresh_resources != NULL) { + char *usn_copy = g_strdup (canonical_usn); + + g_hash_table_insert (resource_browser->priv->fresh_resources, + usn_copy, + usn_copy); + } + if (resource) { /* Remove old timeout */ g_source_destroy (resource->timeout_src); @@ -1032,6 +1072,18 @@ discovery_timeout (gpointer data) resource_browser->priv->timeout_src = NULL; resource_browser->priv->num_discovery = 0; + /* Setup cache refreshing */ + resource_browser->priv->refresh_cache_src = + g_timeout_source_new_seconds (RESCAN_TIMEOUT); + g_source_set_callback + (resource_browser->priv->refresh_cache_src, + refresh_cache, + resource_browser, + NULL); + g_source_attach (resource_browser->priv->refresh_cache_src, + g_main_context_get_thread_default ()); + g_source_unref (resource_browser->priv->refresh_cache_src); + return FALSE; } else return TRUE; @@ -1056,6 +1108,13 @@ start_discovery (GSSDPResourceBrowser *resource_browser) g_main_context_get_thread_default ()); g_source_unref (resource_browser->priv->timeout_src); + + /* Setup a set of responsive resources for cache refreshing */ + resource_browser->priv->fresh_resources = g_hash_table_new_full + (g_str_hash, + g_str_equal, + g_free, + NULL); } /* Stops the sending of discovery messages */ @@ -1067,4 +1126,50 @@ stop_discovery (GSSDPResourceBrowser *resource_browser) resource_browser->priv->timeout_src = NULL; resource_browser->priv->num_discovery = 0; } + if (resource_browser->priv->refresh_cache_src) { + g_source_destroy (resource_browser->priv->refresh_cache_src); + resource_browser->priv->refresh_cache_src = NULL; + } + if (resource_browser->priv->fresh_resources) { + g_hash_table_unref (resource_browser->priv->fresh_resources); + resource_browser->priv->fresh_resources = NULL; + } +} + +static gboolean +refresh_cache_helper (gpointer key, gpointer value, gpointer data) +{ + Resource *resource; + GHashTable *fresh_resources; + + resource = value; + fresh_resources = data; + + if (g_hash_table_lookup_extended (fresh_resources, key, NULL, NULL)) + return FALSE; + else { + g_signal_emit (resource->resource_browser, + signals[RESOURCE_UNAVAILABLE], + 0, + resource->usn); + + return TRUE; + } +} + +/* Removes non-responsive resources */ +static gboolean +refresh_cache (gpointer data) +{ + GSSDPResourceBrowser *resource_browser; + + resource_browser = GSSDP_RESOURCE_BROWSER (data); + g_hash_table_foreach_remove (resource_browser->priv->resources, + refresh_cache_helper, + resource_browser->priv->fresh_resources); + g_hash_table_unref (resource_browser->priv->fresh_resources); + resource_browser->priv->fresh_resources = NULL; + resource_browser->priv->refresh_cache_src = NULL; + + return FALSE; } diff --git a/libgssdp/gssdp-resource-browser.h b/libgssdp/gssdp-resource-browser.h index bf98358..720074e 100644 --- a/libgssdp/gssdp-resource-browser.h +++ b/libgssdp/gssdp-resource-browser.h @@ -113,6 +113,9 @@ gssdp_resource_browser_set_active (GSSDPResourceBrowser *resource_browser, gboolean gssdp_resource_browser_get_active (GSSDPResourceBrowser *resource_browser); +gboolean +gssdp_resource_browser_rescan (GSSDPResourceBrowser *resource_browser); + G_END_DECLS #endif /* __GSSDP_RESOURCE_BROWSER_H__ */ -- 2.7.4