[gupnp] control-point: retry get description url on failure
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gupnp] control-point: retry get description url on failure
- Date: Sat, 18 Jun 2016 15:15:49 +0000 (UTC)
commit cc4550f7e5569644ea7048fe124fae90aa4e9ac6
Author: Jozef Šiška <jozef siska streamunlimited com>
Date: Fri Feb 22 15:31:53 2013 +0100
control-point: retry get description url on failure
Retry 4 times, doubling the intial timeout of 5s
Modified version of original patch
https://bugzilla.gnome.org/show_bug.cgi?id=694450
Signed-off-by: Jens Georg <mail jensge org>
libgupnp/gupnp-control-point.c | 140 ++++++++++++++++++++++++++++++++++------
1 files changed, 120 insertions(+), 20 deletions(-)
---
diff --git a/libgupnp/gupnp-control-point.c b/libgupnp/gupnp-control-point.c
index fe0c7b8..81db087 100644
--- a/libgupnp/gupnp-control-point.c
+++ b/libgupnp/gupnp-control-point.c
@@ -39,6 +39,9 @@
#include "http-headers.h"
#include "xml-util.h"
+#define GUPNP_MAX_DESCRIPTION_DOWNLOAD_RETRIES 4
+#define GUPNP_INITIAL_DESCRIPTION_RETRY_TIMEOUT 5
+
G_DEFINE_TYPE (GUPnPControlPoint,
gupnp_control_point,
GSSDP_TYPE_RESOURCE_BROWSER);
@@ -77,6 +80,9 @@ typedef struct {
char *description_url;
SoupMessage *message;
+ GSource *timeout_source;
+ int tries;
+ int timeout;
} GetDescriptionURLData;
static void
@@ -85,6 +91,24 @@ get_description_url_data_free (GetDescriptionURLData *data)
data->control_point->priv->pending_gets =
g_list_remove (data->control_point->priv->pending_gets, data);
+ if (data->message) {
+ GUPnPContext *context;
+ SoupSession *session;
+
+
+ context = gupnp_control_point_get_context (data->control_point);
+ session = gupnp_context_get_session (context);
+
+ soup_session_cancel_message (session,
+ data->message,
+ SOUP_STATUS_CANCELLED);
+ }
+
+ if (data->timeout_source) {
+ g_source_destroy (data->timeout_source);
+ g_source_unref (data->timeout_source);
+ }
+
g_free (data->udn);
g_free (data->service_type);
g_free (data->description_url);
@@ -92,6 +116,26 @@ get_description_url_data_free (GetDescriptionURLData *data)
g_slice_free (GetDescriptionURLData, data);
}
+static GetDescriptionURLData*
+find_get_description_url_data (GUPnPControlPoint *control_point,
+ const char *udn,
+ const char *service_type)
+{
+ GList *l = control_point->priv->pending_gets;
+
+ while (l) {
+ GetDescriptionURLData *data = l->data;
+
+ if ((g_strcmp0 (udn, data->udn) == 0) &&
+ (service_type == data->service_type ||
+ g_strcmp0 (service_type, data->service_type) == 0))
+ break;
+ l = g_list_next (l);
+ }
+
+ return l ? l->data : NULL;
+}
+
static void
gupnp_control_point_init (GUPnPControlPoint *control_point)
{
@@ -159,18 +203,8 @@ gupnp_control_point_dispose (GObject *object)
/* 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);
}
@@ -528,19 +562,25 @@ description_loaded (GUPnPControlPoint *control_point,
soup_uri_free (url_base);
}
+
+static gboolean
+description_url_retry_timeout (gpointer user_data);
+
/*
* Description URL downloaded.
*/
static void
-got_description_url (G_GNUC_UNUSED SoupSession *session,
- SoupMessage *msg,
- GetDescriptionURLData *data)
+got_description_url (SoupSession *session,
+ SoupMessage *msg,
+ GetDescriptionURLData *data)
{
GUPnPXMLDoc *doc;
if (msg->status_code == SOUP_STATUS_CANCELLED)
return;
+ data->message = NULL;
+
/* Now, make sure again this document is not already cached. If it is,
* we re-use the cached one. */
doc = g_hash_table_lookup (data->control_point->priv->doc_cache,
@@ -590,12 +630,34 @@ got_description_url (G_GNUC_UNUSED SoupSession *session,
g_object_unref (doc);
} else
g_warning ("Failed to parse %s", data->description_url);
- } else
- g_warning ("Failed to GET %s: %s",
- data->description_url,
- msg->reason_phrase);
- get_description_url_data_free (data);
+ get_description_url_data_free (data);
+ } else {
+ GMainContext *async_context;
+
+ /* Retry GET after a timeout */
+ async_context = soup_session_get_async_context (session);
+
+ data->tries--;
+
+ if (data->tries > 0) {
+ g_warning ("Failed to GET %s: %s, retrying in %d seconds",
+ data->description_url,
+ msg->reason_phrase,
+ data->timeout);
+
+ data->timeout_source = g_timeout_source_new_seconds
+ (data->timeout);
+ g_source_set_callback (data->timeout_source,
+ description_url_retry_timeout,
+ data,
+ NULL);
+ g_source_attach (data->timeout_source, async_context);
+ data->timeout <<= 1;
+ } else {
+ g_warning ("Maximum number of retries failed, not trying again");
+ }
+ }
}
/*
@@ -610,7 +672,9 @@ static void
load_description (GUPnPControlPoint *control_point,
const char *description_url,
const char *udn,
- const char *service_type)
+ const char *service_type,
+ guint max_tries,
+ guint timeout)
{
GUPnPXMLDoc *doc;
@@ -635,6 +699,8 @@ load_description (GUPnPControlPoint *control_point,
data = g_slice_new (GetDescriptionURLData);
+ data->tries = max_tries;
+ data->timeout = timeout;
data->message = soup_message_new (SOUP_METHOD_GET,
description_url);
if (data->message == NULL) {
@@ -653,6 +719,7 @@ load_description (GUPnPControlPoint *control_point,
data->udn = g_strdup (udn);
data->service_type = g_strdup (service_type);
data->description_url = g_strdup (description_url);
+ data->timeout_source = NULL;
control_point->priv->pending_gets =
g_list_prepend (control_point->priv->pending_gets,
@@ -666,6 +733,26 @@ load_description (GUPnPControlPoint *control_point,
}
}
+/*
+ * Retry the description download
+ */
+static gboolean
+description_url_retry_timeout (gpointer user_data)
+{
+ GetDescriptionURLData *data = (GetDescriptionURLData *) user_data;
+
+ load_description (data->control_point,
+ data->description_url,
+ data->udn,
+ data->service_type,
+ data->tries,
+ data->timeout);
+
+ get_description_url_data_free (data);
+
+ return FALSE;
+}
+
static gboolean
parse_usn (const char *usn,
char **udn,
@@ -771,7 +858,9 @@ gupnp_control_point_resource_available (GSSDPResourceBrowser *resource_browser,
load_description (control_point,
locations->data,
udn,
- service_type);
+ service_type,
+ GUPNP_MAX_DESCRIPTION_DOWNLOAD_RETRIES,
+ GUPNP_INITIAL_DESCRIPTION_RETRY_TIMEOUT);
g_free (udn);
g_free (service_type);
@@ -784,6 +873,7 @@ gupnp_control_point_resource_unavailable
{
GUPnPControlPoint *control_point;
char *udn, *service_type;
+ GetDescriptionURLData *get_data;
control_point = GUPNP_CONTROL_POINT (resource_browser);
@@ -834,6 +924,16 @@ gupnp_control_point_resource_unavailable
}
}
+ /* Find the description get request if it has not finished yet and stop
+ * and remove it */
+ get_data = find_get_description_url_data (control_point,
+ udn,
+ service_type);
+
+ if (get_data) {
+ get_description_url_data_free (get_data);
+ }
+
g_free (udn);
g_free (service_type);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]