[grilo] net: move cache and request to a private file
- From: Victor Manuel Jaquez Leal <vjaquez src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [grilo] net: move cache and request to a private file
- Date: Mon, 30 Apr 2012 15:56:19 +0000 (UTC)
commit 6a80f062ac4814a26e2815ed99119369197ee836
Author: VÃctor Manuel JÃquez Leal <vjaquez igalia com>
Date: Thu Apr 26 16:54:56 2012 +0200
net: move cache and request to a private file
Signed-off-by: VÃctor Manuel JÃquez Leal <vjaquez igalia com>
libs/net/Makefile.am | 9 +
libs/net/grl-net-private.c | 91 ++++++++
libs/net/grl-net-private.h | 80 +++++++
libs/net/grl-net-soup-stable.c | 186 ++++++++++++++++
libs/net/grl-net-soup-unstable.c | 292 +++++++++++++++++++++++++
libs/net/grl-net-wc.c | 440 ++------------------------------------
libs/net/grl-net-wc.h | 2 +
7 files changed, 677 insertions(+), 423 deletions(-)
---
diff --git a/libs/net/Makefile.am b/libs/net/Makefile.am
index 5414369..b756461 100644
--- a/libs/net/Makefile.am
+++ b/libs/net/Makefile.am
@@ -12,6 +12,7 @@ libgrlnet_ GRL_MAJORMINOR@_la_DEPENDENCIES = \
$(top_builddir)/src/lib GRL_NAME@.la
libgrlnet_ GRL_MAJORMINOR@_la_SOURCES = \
+ grl-net-private.c \
grl-net-wc.c
libgrlnet_ GRL_MAJORMINOR@_la_CFLAGS = \
@@ -23,6 +24,11 @@ libgrlnet_ GRL_MAJORMINOR@_la_CFLAGS = \
if BUILD_GRILO_NET_WITH_CACHE
libgrlnet_ GRL_MAJORMINOR@_la_CFLAGS += \
-DLIBSOUP_WITH_CACHE
+libgrlnet_ GRL_MAJORMINOR@_la_SOURCES += \
+ grl-net-soup-unstable.c
+else
+libgrlnet_ GRL_MAJORMINOR@_la_SOURCES += \
+ grl-net-soup-stable.c
endif
libgrlnet_ GRL_MAJORMINOR@_la_LIBADD = \
@@ -40,6 +46,9 @@ libgrlnet_ GRL_MAJORMINOR@include_HEADERS = \
grl-net-wc.h \
grl-net.h
+noinst_HEADERS = \
+ grl-net-private.h
+
MAINTAINERCLEANFILES = \
*.in \
*.gir \
diff --git a/libs/net/grl-net-private.c b/libs/net/grl-net-private.c
new file mode 100644
index 0000000..7c1e557
--- /dev/null
+++ b/libs/net/grl-net-private.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * Contact: Iago Toral Quiroga <itoral igalia com>
+ *
+ * Authors: VÃctor M. JÃquez L. <vjaquez igalia com>
+ * Juan A. Suarez Romero <jasuarez igalia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "grl-net-private.h"
+
+void
+parse_error (guint status,
+ const gchar *reason,
+ const gchar *response,
+ GSimpleAsyncResult *result)
+{
+ if (!response || *response == '\0')
+ response = reason;
+
+ switch (status) {
+ case SOUP_STATUS_CANT_RESOLVE:
+ case SOUP_STATUS_CANT_CONNECT:
+ case SOUP_STATUS_SSL_FAILED:
+ case SOUP_STATUS_IO_ERROR:
+ g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
+ GRL_NET_WC_ERROR_NETWORK_ERROR,
+ "Cannot connect to the server");
+ return;
+ case SOUP_STATUS_CANT_RESOLVE_PROXY:
+ case SOUP_STATUS_CANT_CONNECT_PROXY:
+ g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
+ GRL_NET_WC_ERROR_PROXY_ERROR,
+ "Cannot connect to the proxy server");
+ return;
+ case SOUP_STATUS_INTERNAL_SERVER_ERROR: /* 500 */
+ case SOUP_STATUS_MALFORMED:
+ case SOUP_STATUS_BAD_REQUEST: /* 400 */
+ g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
+ GRL_NET_WC_ERROR_PROTOCOL_ERROR,
+ "Invalid request URI or header: %s",
+ response);
+ return;
+ case SOUP_STATUS_UNAUTHORIZED: /* 401 */
+ case SOUP_STATUS_FORBIDDEN: /* 403 */
+ g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
+ GRL_NET_WC_ERROR_AUTHENTICATION_REQUIRED,
+ "Authentication required: %s", response);
+ return;
+ case SOUP_STATUS_NOT_FOUND: /* 404 */
+ g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
+ GRL_NET_WC_ERROR_NOT_FOUND,
+ "The requested resource was not found: %s",
+ response);
+ return;
+ case SOUP_STATUS_CONFLICT: /* 409 */
+ case SOUP_STATUS_PRECONDITION_FAILED: /* 412 */
+ g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
+ GRL_NET_WC_ERROR_CONFLICT,
+ "The entry has been modified since it was downloaded: %s",
+ response);
+ return;
+ case SOUP_STATUS_CANCELLED:
+ g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
+ GRL_NET_WC_ERROR_CANCELLED,
+ "Operation was cancelled");
+ return;
+ default:
+ g_message ("Unhandled status: %s", soup_status_get_phrase (status));
+ }
+}
diff --git a/libs/net/grl-net-private.h b/libs/net/grl-net-private.h
new file mode 100644
index 0000000..184fb16
--- /dev/null
+++ b/libs/net/grl-net-private.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * Contact: Iago Toral Quiroga <itoral igalia com>
+ *
+ * Authors: VÃctor M. JÃquez L. <vjaquez igalia com>
+ * Juan A. Suarez Romero <jasuarez igalia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef _GRL_NET_PRIVATE_H_
+#define _GRL_NET_PRIVATE_H_
+
+#include <libsoup/soup.h>
+#include <grilo.h>
+
+#include "grl-net-wc.h"
+
+G_BEGIN_DECLS
+
+struct _GrlNetWcPrivate {
+ SoupSession *session;
+ SoupLoggerLogLevel log_level;
+ guint throttling; /* throttling in secs */
+ GTimeVal last_request; /* last request time */
+ GQueue *pending; /* closure queue for delayed requests */
+ guint cache_size; /* cache size in Mb */
+ void *requester;
+ gchar *previous_data;
+};
+
+void parse_error (guint status,
+ const gchar *reason,
+ const gchar *response,
+ GSimpleAsyncResult *result);
+
+void get_url_now (GrlNetWc *self,
+ const char *url,
+ GAsyncResult *result,
+ GCancellable *cancellable);
+
+void get_content (GrlNetWc *self,
+ void *op,
+ gchar **content,
+ gsize *length);
+
+void init_requester (GrlNetWc *self);
+
+void finalize_requester (GrlNetWc *self);
+
+void cache_down (GrlNetWc *self);
+
+void cache_up (GrlNetWc *self);
+
+gboolean cache_is_available (GrlNetWc *self);
+
+void cache_set_size (GrlNetWc *self, guint size);
+
+guint cache_get_size (GrlNetWc *self);
+
+void free_op_res (void *op);
+
+G_END_DECLS
+
+#endif /* _GRL_NET_PRIVATE_H_ */
diff --git a/libs/net/grl-net-soup-stable.c b/libs/net/grl-net-soup-stable.c
new file mode 100644
index 0000000..d1e8926
--- /dev/null
+++ b/libs/net/grl-net-soup-stable.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * Contact: Iago Toral Quiroga <itoral igalia com>
+ *
+ * Authors: VÃctor M. JÃquez L. <vjaquez igalia com>
+ * Juan A. Suarez Romero <jasuarez igalia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <libsoup/soup.h>
+
+#include "grl-net-private.h"
+
+static void
+reply_cb (SoupSession *session,
+ SoupMessage *msg,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ gulong cancel_signal;
+
+ cancel_signal = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (msg),
+ "cancel-signal"));
+ if (cancel_signal) {
+ GCancellable *cancellable;
+
+ cancellable = g_object_get_data (G_OBJECT (msg), "cancellable");
+ g_signal_handler_disconnect (cancellable, cancel_signal);
+ }
+
+ result = G_SIMPLE_ASYNC_RESULT (user_data);
+
+ if (msg->status_code != SOUP_STATUS_OK) {
+ parse_error (msg->status_code,
+ msg->reason_phrase,
+ msg->response_body->data,
+ result);
+ }
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+}
+
+static void
+message_cancel_cb (GCancellable *cancellable,
+ SoupMessage *msg)
+{
+ if (msg)
+ soup_session_cancel_message (g_object_get_data (G_OBJECT (msg), "session"),
+ msg, SOUP_STATUS_CANCELLED);
+
+}
+
+void
+get_url_now (GrlNetWc *self,
+ const char *url,
+ GAsyncResult *result,
+ GCancellable *cancellable)
+{
+ SoupMessage *msg;
+ gulong cancel_signal;
+
+ msg = soup_message_new (SOUP_METHOD_GET, url);
+
+ if (!msg) {
+ g_simple_async_result_set_error (G_SIMPLE_ASYNC_RESULT (result),
+ GRL_NET_WC_ERROR,
+ GRL_NET_WC_ERROR_PROTOCOL_ERROR,
+ "Malformed URL: %s", url);
+ g_simple_async_result_complete_in_idle (G_SIMPLE_ASYNC_RESULT (result));
+ g_object_unref (result);
+
+ return;
+ }
+
+ g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result),
+ msg, NULL);
+
+ cancel_signal = 0;
+ if (cancellable) {
+ g_object_set_data (G_OBJECT (msg),
+ "cancellable",
+ cancellable);
+ cancel_signal = g_signal_connect (cancellable,
+ "cancelled",
+ G_CALLBACK (message_cancel_cb),
+ msg);
+ }
+
+ g_object_set_data (G_OBJECT (msg),
+ "cancel-signal",
+ GUINT_TO_POINTER (cancel_signal));
+ g_object_set_data_full (G_OBJECT (msg),
+ "session",
+ g_object_ref (self->priv->session),
+ g_object_unref);
+
+ soup_session_queue_message (self->priv->session,
+ msg,
+ reply_cb,
+ result);
+}
+
+void
+get_content (GrlNetWc *self,
+ void *op,
+ gchar **content,
+ gsize *length)
+{
+ SoupMessage *msg = op;
+
+ if (content)
+ *content = (gchar *) msg->response_body->data;
+
+ if (length)
+ *length = (gsize) msg->response_body->length;
+}
+
+void
+init_requester (GrlNetWc *self)
+{
+ /* noop */
+}
+
+void
+finalize_requester (GrlNetWc *self)
+{
+ /* noop */
+}
+
+void
+cache_down (GrlNetWc *self)
+{
+ /* noop */
+}
+
+void
+cache_up (GrlNetWc *self)
+{
+ GRL_INFO ("Cache not supported");
+}
+
+gboolean
+cache_is_available (GrlNetWc *self)
+{
+ return FALSE;
+}
+
+void
+cache_set_size (GrlNetWc *self, guint size)
+{
+ /* noop */
+}
+
+guint
+cache_get_size (GrlNetWc *self)
+{
+ GRL_INFO ("Cache not supported");
+ return 0;
+}
+
+void
+free_op_res (void *op)
+{
+ /* noop */
+}
diff --git a/libs/net/grl-net-soup-unstable.c b/libs/net/grl-net-soup-unstable.c
new file mode 100644
index 0000000..de96f50
--- /dev/null
+++ b/libs/net/grl-net-soup-unstable.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * Contact: Iago Toral Quiroga <itoral igalia com>
+ *
+ * Authors: VÃctor M. JÃquez L. <vjaquez igalia com>
+ * Juan A. Suarez Romero <jasuarez igalia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Using the cache feature requires to use the unstable API */
+#define LIBSOUP_USE_UNSTABLE_REQUEST_API
+
+#include <libsoup/soup-cache.h>
+#include <libsoup/soup-requester.h>
+#include <libsoup/soup-request-http.h>
+
+#include "grl-net-private.h"
+
+#define GRL_LOG_DOMAIN_DEFAULT wc_log_domain
+GRL_LOG_DOMAIN_EXTERN(wc_log_domain);
+
+SoupCache *cache;
+guint cache_size;
+
+void
+init_requester (GrlNetWc *self)
+{
+ GrlNetWcPrivate *priv = self->priv;
+
+ priv->requester = soup_requester_new ();
+ soup_session_add_feature (priv->session,
+ SOUP_SESSION_FEATURE (priv->requester));
+}
+
+void
+finalize_requester (GrlNetWc *self)
+{
+ GrlNetWcPrivate *priv = self->priv;
+
+ cache_down (self);
+ g_free (priv->previous_data);
+ g_object_unref (priv->requester);
+}
+
+void
+cache_down (GrlNetWc *self)
+{
+ GrlNetWcPrivate *priv = self->priv;
+ GRL_DEBUG ("cache down: %p", cache);
+
+ if (!cache)
+ return;
+
+ soup_session_remove_feature (priv->session, SOUP_SESSION_FEATURE (cache));
+ g_object_unref (cache);
+ cache = NULL;
+}
+
+void
+cache_up (GrlNetWc *self)
+{
+ GrlNetWcPrivate *priv = self->priv;
+ gchar *dir;
+
+ GRL_DEBUG ("cache up: %p", cache);
+
+ if (cache)
+ return;
+
+ dir = g_build_filename (g_get_user_cache_dir (),
+ g_get_prgname (),
+ "grilo",
+ NULL);
+ cache = soup_cache_new (dir, SOUP_CACHE_SINGLE_USER);
+ g_free (dir);
+
+ soup_cache_set_max_size (cache, cache_size);
+
+ soup_session_add_feature (priv->session,
+ SOUP_SESSION_FEATURE (cache));
+}
+
+gboolean
+cache_is_available (GrlNetWc *self)
+{
+ return cache != NULL;
+}
+
+void
+cache_set_size (GrlNetWc *self, guint size)
+{
+ if (!cache || size == cache_size)
+ return;
+
+ cache_size = size;
+ soup_cache_set_max_size (cache, cache_size);
+}
+
+guint
+cache_get_size (GrlNetWc *self)
+{
+ return cache_size;
+}
+
+struct request_res {
+ SoupRequest *request;
+ gchar *buffer;
+ gsize length;
+ gsize offset;
+};
+
+static void
+read_async_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
+ struct request_res *rr = g_simple_async_result_get_op_res_gpointer (result);;
+
+ GError *error = NULL;
+ gssize s = g_input_stream_read_finish (G_INPUT_STREAM (source), res, &error);
+
+ gsize to_read;
+
+ if (s > 0) {
+ /* Continue reading */
+ rr->offset += s;
+ to_read = rr->length - rr->offset;
+
+ if (!to_read) {
+ /* Buffer is not enough; we need to assign more space */
+ rr->length *= 2;
+ rr->buffer = g_renew (gchar, rr->buffer, rr->length);
+ to_read = rr->length - rr->offset;
+ }
+
+ g_input_stream_read_async (G_INPUT_STREAM (source),
+ rr->buffer + rr->offset,
+ to_read,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ read_async_cb,
+ user_data);
+ return;
+ }
+
+ /* Put the end of string */
+ rr->buffer[rr->offset] = '\0';
+
+ g_input_stream_close (G_INPUT_STREAM (source), NULL, NULL);
+
+ if (error) {
+ if (error->code == G_IO_ERROR_CANCELLED) {
+ g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
+ GRL_NET_WC_ERROR_CANCELLED,
+ "Operation was cancelled");
+ } else {
+ g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
+ GRL_NET_WC_ERROR_UNAVAILABLE,
+ "Data not available");
+ }
+
+ g_error_free (error);
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+ return;
+ }
+
+ {
+ SoupMessage *msg =
+ soup_request_http_get_message (SOUP_REQUEST_HTTP (rr->request));
+
+ if (msg && msg->status_code != SOUP_STATUS_OK) {
+ parse_error (msg->status_code,
+ msg->reason_phrase,
+ msg->response_body->data,
+ G_SIMPLE_ASYNC_RESULT (user_data));
+ g_object_unref (msg);
+ }
+ }
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+}
+
+
+static void
+reply_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
+ struct request_res *rr = g_simple_async_result_get_op_res_gpointer (result);
+
+ GError *error = NULL;
+ GInputStream *in = soup_request_send_finish (rr->request, res, &error);
+
+ if (error) {
+ g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
+ GRL_NET_WC_ERROR_UNAVAILABLE,
+ "Data not available");
+ g_error_free (error);
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+ return;
+ }
+
+ rr->length = soup_request_get_content_length (rr->request) + 1;
+ if (rr->length == 1)
+ rr->length = 50 * 1024;
+
+ rr->buffer = g_new (gchar, rr->length);
+
+ g_input_stream_read_async (in,
+ rr->buffer,
+ rr->length,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ read_async_cb,
+ user_data);
+}
+
+void
+get_url_now (GrlNetWc *self,
+ const char *url,
+ GAsyncResult *result,
+ GCancellable *cancellable)
+{
+ GrlNetWcPrivate *priv = self->priv;
+ struct request_res *rr = g_slice_new0 (struct request_res);
+
+ g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result),
+ rr,
+ NULL);
+
+ rr->request = soup_requester_request (priv->requester, url, NULL);
+ soup_request_send_async (rr->request, cancellable, reply_cb, result);
+}
+
+void
+get_content (GrlNetWc *self,
+ void *op,
+ gchar **content,
+ gsize *length)
+{
+ GrlNetWcPrivate *priv = self->priv;
+ struct request_res *rr = op;
+
+ if (priv->previous_data)
+ g_free (priv->previous_data);
+
+ priv->previous_data = rr->buffer;
+
+ if (content)
+ *content = self->priv->previous_data;
+ else
+ g_free (rr->buffer);
+
+ if (length)
+ *length = rr->offset;
+}
+
+void
+free_op_res (void *op)
+{
+ struct request_res *rr = op;
+
+ g_object_unref (rr->request);
+ g_slice_free (struct request_res, rr);
+}
diff --git a/libs/net/grl-net-wc.c b/libs/net/grl-net-wc.c
index 3ab04e5..7468d88 100644
--- a/libs/net/grl-net-wc.c
+++ b/libs/net/grl-net-wc.c
@@ -39,20 +39,12 @@
#include <string.h>
#include <libsoup/soup.h>
-#ifdef LIBSOUP_WITH_CACHE
-/* Using the cache feature requires to use the unstable API */
-#define LIBSOUP_USE_UNSTABLE_REQUEST_API
-#define BUFFER_SIZE (50*1024)
-#include <libsoup/soup-cache.h>
-#include <libsoup/soup-requester.h>
-#include <libsoup/soup-request-http.h>
-#endif
-
#include <grilo.h>
#include "grl-net-wc.h"
+#include "grl-net-private.h"
#define GRL_LOG_DOMAIN_DEFAULT wc_log_domain
-GRL_LOG_DOMAIN_STATIC(wc_log_domain);
+GRL_LOG_DOMAIN(wc_log_domain);
enum {
PROP_0,
@@ -67,36 +59,6 @@ enum {
GRL_TYPE_NET_WC, \
GrlNetWcPrivate))
-#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
-static SoupCache *cache = NULL;
-static void cache_down(GrlNetWc *self);
-#endif
-
-static guint cache_size;
-
-struct _GrlNetWcPrivate {
- SoupSession *session;
- SoupLoggerLogLevel log_level;
-#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
- SoupRequester *requester;
- SoupCache *cache;
- gchar *previous_data;
-#endif
- guint cache_size;
- guint throttling;
- GTimeVal last_request;
- GQueue *pending; /* closure queue for delayed requests */
-};
-
-#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
-typedef struct {
- SoupRequest *request;
- gchar *buffer;
- gsize length;
- gsize offset;
-} RequestResult;
-#endif
-
GQuark
grl_net_wc_error_quark (void)
{
@@ -211,12 +173,7 @@ grl_net_wc_init (GrlNetWc *wc)
wc->priv->pending = g_queue_new ();
set_thread_context (wc);
-
-#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
- wc->priv->requester = soup_requester_new();
- soup_session_add_feature (wc->priv->session,
- SOUP_SESSION_FEATURE (wc->priv->requester));
-#endif
+ init_requester (wc);
}
static void
@@ -226,11 +183,10 @@ grl_net_wc_finalize (GObject *object)
wc = GRL_NET_WC (object);
grl_net_wc_flush_delayed_requests (wc);
-#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
+
cache_down (wc);
- g_free (wc->priv->previous_data);
- g_object_unref (wc->priv->requester);
-#endif
+ finalize_requester (wc);
+
g_queue_free (wc->priv->pending);
g_object_unref (wc->priv->session);
@@ -283,290 +239,16 @@ grl_net_wc_get_property (GObject *object,
g_value_set_uint (value, wc->priv->throttling);
break;
case PROP_CACHE:
-#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
- g_value_set_boolean (value, wc->priv->cache != NULL);
-#else
- g_value_set_boolean (value, FALSE);
-#endif
+ g_value_set_boolean(value, cache_is_available (wc));
break;
case PROP_CACHE_SIZE:
- g_value_set_uint (value, wc->priv->cache_size);
+ g_value_set_uint (value, cache_get_size (wc));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (wc, propid, pspec);
}
}
-static inline void
-parse_error (guint status,
- const gchar *reason,
- const gchar *response,
- GSimpleAsyncResult *result)
-{
- if (!response || *response == '\0')
- response = reason;
-
- switch (status) {
- case SOUP_STATUS_CANT_RESOLVE:
- case SOUP_STATUS_CANT_CONNECT:
- case SOUP_STATUS_SSL_FAILED:
- case SOUP_STATUS_IO_ERROR:
- g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
- GRL_NET_WC_ERROR_NETWORK_ERROR,
- "Cannot connect to the server");
- return;
- case SOUP_STATUS_CANT_RESOLVE_PROXY:
- case SOUP_STATUS_CANT_CONNECT_PROXY:
- g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
- GRL_NET_WC_ERROR_PROXY_ERROR,
- "Cannot connect to the proxy server");
- return;
- case SOUP_STATUS_INTERNAL_SERVER_ERROR: /* 500 */
- case SOUP_STATUS_MALFORMED:
- case SOUP_STATUS_BAD_REQUEST: /* 400 */
- g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
- GRL_NET_WC_ERROR_PROTOCOL_ERROR,
- "Invalid request URI or header: %s",
- response);
- return;
- case SOUP_STATUS_UNAUTHORIZED: /* 401 */
- case SOUP_STATUS_FORBIDDEN: /* 403 */
- g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
- GRL_NET_WC_ERROR_AUTHENTICATION_REQUIRED,
- "Authentication required: %s", response);
- return;
- case SOUP_STATUS_NOT_FOUND: /* 404 */
- g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
- GRL_NET_WC_ERROR_NOT_FOUND,
- "The requested resource was not found: %s",
- response);
- return;
- case SOUP_STATUS_CONFLICT: /* 409 */
- case SOUP_STATUS_PRECONDITION_FAILED: /* 412 */
- g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
- GRL_NET_WC_ERROR_CONFLICT,
- "The entry has been modified since it was downloaded: %s",
- response);
- return;
- case SOUP_STATUS_CANCELLED:
- g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
- GRL_NET_WC_ERROR_CANCELLED,
- "Operation was cancelled");
- return;
- default:
- g_message ("Unhandled status: %s", soup_status_get_phrase (status));
- }
-}
-
-#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
-static void
-read_async_cb (GObject *source, GAsyncResult *res, gpointer user_data)
-{
- GSimpleAsyncResult *result;
- RequestResult *rr;
- SoupMessage *msg;
- GError *error = NULL;
- gsize to_read;
- gssize s;
-
- result = G_SIMPLE_ASYNC_RESULT (user_data);
- rr = g_simple_async_result_get_op_res_gpointer (result);
-
- s = g_input_stream_read_finish (G_INPUT_STREAM (source), res, &error);
- if (s > 0) {
- /* Continue reading */
- rr->offset += s;
- to_read = rr->length - rr->offset;
- if (!to_read) {
- /* Buffer is not enough; we need to assign more space */
- rr->length *= 2;
- rr->buffer = g_renew (gchar, rr->buffer, rr->length);
- to_read = rr->length - rr->offset;
- }
- g_input_stream_read_async (G_INPUT_STREAM (source), rr->buffer + rr->offset, to_read, G_PRIORITY_DEFAULT, NULL, read_async_cb, user_data);
- return;
- }
-
- /* Put the end of string */
- rr->buffer[rr->offset] = '\0';
-
- g_input_stream_close (G_INPUT_STREAM (source), NULL, NULL);
-
- if (error) {
- if (error->code == G_IO_ERROR_CANCELLED) {
- g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
- GRL_NET_WC_ERROR_CANCELLED,
- "Operation was cancelled");
- } else {
- g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
- GRL_NET_WC_ERROR_UNAVAILABLE,
- "Data not available");
- }
- g_error_free (error);
-
- g_simple_async_result_complete (result);
- g_object_unref (result);
- return;
- }
-
- msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (rr->request));
-
- if (msg) {
- if (msg->status_code != SOUP_STATUS_OK) {
- parse_error (msg->status_code,
- msg->reason_phrase,
- msg->response_body->data,
- G_SIMPLE_ASYNC_RESULT (user_data));
- g_object_unref (msg);
- }
- }
-
- g_simple_async_result_complete (result);
- g_object_unref (result);
-}
-
-static void
-reply_cb (GObject *source, GAsyncResult *res, gpointer user_data)
-{
- GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
- RequestResult *rr = g_simple_async_result_get_op_res_gpointer (result);
- GError *error = NULL;
-
- GInputStream *in = soup_request_send_finish (rr->request, res, &error);
-
- if (error != NULL) {
- g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
- GRL_NET_WC_ERROR_UNAVAILABLE,
- "Data not available");
- g_error_free (error);
-
- g_simple_async_result_complete (result);
- g_object_unref (result);
- return;
- }
-
- rr->length = soup_request_get_content_length (rr->request) + 1;
- if (rr->length == 1) {
- rr->length = BUFFER_SIZE;
- }
- rr->buffer = g_new (gchar, rr->length);
- g_input_stream_read_async (in, rr->buffer, rr->length, G_PRIORITY_DEFAULT, NULL, read_async_cb, user_data);
-}
-
-#else
-
-static void
-reply_cb (SoupSession *session,
- SoupMessage *msg,
- gpointer user_data)
-{
- GSimpleAsyncResult *result;
- gulong cancel_signal;
-
- cancel_signal = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (msg),
- "cancel-signal"));
- if (cancel_signal) {
- GCancellable *cancellable;
-
- cancellable = g_object_get_data (G_OBJECT (msg), "cancellable");
- g_signal_handler_disconnect (cancellable, cancel_signal);
- }
-
- result = G_SIMPLE_ASYNC_RESULT (user_data);
-
- if (msg->status_code != SOUP_STATUS_OK) {
- parse_error (msg->status_code,
- msg->reason_phrase,
- msg->response_body->data,
- result);
- }
-
- g_simple_async_result_complete (result);
- g_object_unref (result);
-}
-
-static void
-message_cancel_cb (GCancellable *cancellable,
- SoupMessage *msg)
-{
- if (msg)
- soup_session_cancel_message (g_object_get_data (G_OBJECT (msg), "session"),
- msg, SOUP_STATUS_CANCELLED);
-
-}
-#endif
-
-#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
-static void
-get_url_now (GrlNetWc *self,
- const char *url,
- GAsyncResult *result,
- GCancellable *cancellable)
-{
- RequestResult *rr = g_slice_new0 (RequestResult);
-
- g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result),
- rr,
- NULL);
-
- rr->request = soup_requester_request (self->priv->requester, url, NULL);
-
- soup_request_send_async (rr->request, cancellable, reply_cb, result);
-}
-
-#else
-
-static void
-get_url_now (GrlNetWc *self,
- const char *url,
- GAsyncResult *result,
- GCancellable *cancellable)
-{
- SoupMessage *msg;
- gulong cancel_signal;
-
- msg = soup_message_new (SOUP_METHOD_GET, url);
-
- if (!msg) {
- g_simple_async_result_set_error (G_SIMPLE_ASYNC_RESULT (result),
- GRL_NET_WC_ERROR,
- GRL_NET_WC_ERROR_PROTOCOL_ERROR,
- "Malformed URL: %s", url);
- g_simple_async_result_complete_in_idle (G_SIMPLE_ASYNC_RESULT (result));
- g_object_unref (result);
-
- return;
- }
-
- g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result),
- msg, NULL);
-
- cancel_signal = 0;
- if (cancellable) {
- g_object_set_data (G_OBJECT (msg),
- "cancellable",
- cancellable);
- cancel_signal = g_signal_connect (cancellable,
- "cancelled",
- G_CALLBACK (message_cancel_cb),
- msg);
- }
-
- g_object_set_data (G_OBJECT (msg),
- "cancel-signal",
- GUINT_TO_POINTER (cancel_signal));
- g_object_set_data_full (G_OBJECT (msg),
- "session",
- g_object_ref (self->priv->session),
- g_object_unref);
-
- soup_session_queue_message (self->priv->session,
- msg,
- reply_cb,
- result);
-}
-#endif
-
struct request_clos {
GrlNetWc *self;
char *url;
@@ -632,42 +314,6 @@ get_url (GrlNetWc *self,
g_queue_push_head (self->priv->pending, c);
}
-#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
-static void
-update_cache_size ()
-{
- guint size_in_bytes = cache_size * 1024 * 1024;
- soup_cache_set_max_size (cache, size_in_bytes);
-}
-
-static void
-cache_down (GrlNetWc *self)
-{
- soup_session_remove_feature (self->priv->session,
- SOUP_SESSION_FEATURE (self->priv->cache));
- g_object_unref (self->priv->cache);
- self->priv->cache = NULL;
-}
-
-static void
-cache_up (GrlNetWc *self)
-{
- if (!cache) {
- gchar *cache_dir = g_build_filename (g_get_user_cache_dir (),
- g_get_prgname (),
- "grilo",
- NULL);
- cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER);
- update_cache_size ();
- g_free (cache_dir);
- }
-
- self->priv->cache = g_object_ref (cache);
- soup_session_add_feature (self->priv->session,
- SOUP_SESSION_FEATURE (self->priv->cache));
-}
-#endif
-
/**
* grl_net_wc_new:
*
@@ -742,46 +388,17 @@ grl_net_wc_request_finish (GrlNetWc *self,
g_warn_if_fail (g_simple_async_result_get_source_tag (res) ==
grl_net_wc_request_async);
-#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
- RequestResult *rr = g_simple_async_result_get_op_res_gpointer (res);
-#endif
+ void *op = g_simple_async_result_get_op_res_gpointer (res);
if (g_simple_async_result_propagate_error (res, error) == TRUE) {
ret = FALSE;
goto end_func;
}
-#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
- if (self->priv->previous_data) {
- g_free (self->priv->previous_data);
- }
-
- self->priv->previous_data = rr->buffer;
-
- if (content) {
- *content = self->priv->previous_data;
- } else {
- g_free (rr->buffer);
- }
-
- if (length) {
- *length = rr->offset;
- }
-
-#else
- SoupMessage *msg = (SoupMessage *) g_simple_async_result_get_op_res_gpointer (res);
-
- if (content != NULL)
- *content = (gchar *) msg->response_body->data;
- if (length != NULL)
- *length = (gsize) msg->response_body->length;
-#endif
+ get_content(self, op, content, length);
end_func:
-#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
- g_object_unref (rr->request);
- g_slice_free (RequestResult, rr);
-#endif
+ free_op_res (op);
return ret;
}
@@ -859,22 +476,10 @@ grl_net_wc_set_cache (GrlNetWc *self,
{
g_return_if_fail (GRL_IS_NET_WC (self));
-#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
- if (use_cache) {
- if (self->priv->cache) {
- return;
- }
-
+ if (use_cache)
cache_up (self);
-
- } else {
- if (self->priv->cache) {
- cache_down (self);
- }
- }
-#else
- GRL_WARNING ("Cache not supported");
-#endif
+ else
+ cache_down (self);
}
/**
@@ -893,20 +498,7 @@ grl_net_wc_set_cache_size (GrlNetWc *self,
{
g_return_if_fail (GRL_IS_NET_WC (self));
- if (self->priv->cache_size == size) {
- return;
- }
-
- /* Change the global cache size */
- cache_size -= self->priv->cache_size;
- self->priv->cache_size = size;
- cache_size += self->priv->cache_size;
-
-#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
- if (self->priv->cache) {
- update_cache_size ();
- }
-#endif
+ cache_set_size (self, size);
}
/**
@@ -918,6 +510,8 @@ grl_net_wc_set_cache_size (GrlNetWc *self,
void
grl_net_wc_flush_delayed_requests (GrlNetWc *self)
{
+ g_return_if_fail (GRL_IS_NET_WC (self));
+
GrlNetWcPrivate *priv = self->priv;
struct request_clos *c;
diff --git a/libs/net/grl-net-wc.h b/libs/net/grl-net-wc.h
index 125b265..fc472e0 100644
--- a/libs/net/grl-net-wc.h
+++ b/libs/net/grl-net-wc.h
@@ -96,6 +96,8 @@ struct _GrlNetWc
/**
* GrlNetWcClass:
* @parent_class: the parent class structure
+ * @cache: class variable for cache definition
+ * @cache_size: class variable for the cache size value
*
* Grilo web client helper class.
*
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]