diff options
author | Rob Bradford <rob@linux.intel.com> | 2010-08-25 16:36:33 +0100 |
---|---|---|
committer | Rob Bradford <rob@linux.intel.com> | 2010-09-02 10:25:29 +0100 |
commit | 232881ed1e61ffa4561bca240b87a35f37d4f3ec (patch) | |
tree | bc006b450a0b2828246d2472b649ad0285ae9dc6 | |
parent | 4e7ae7faadaa9039511f21eb2431f5c9dcee0668 (diff) |
proxy-call: Add first pass at continuous call mode
-rw-r--r-- | rest/rest-proxy-call-private.h | 1 | ||||
-rw-r--r-- | rest/rest-proxy-call.c | 129 | ||||
-rw-r--r-- | rest/rest-proxy-call.h | 14 |
3 files changed, 144 insertions, 0 deletions
diff --git a/rest/rest-proxy-call-private.h b/rest/rest-proxy-call-private.h index 50a2a0b..584a77b 100644 --- a/rest/rest-proxy-call-private.h +++ b/rest/rest-proxy-call-private.h @@ -30,6 +30,7 @@ G_BEGIN_DECLS typedef struct _RestProxyCallAsyncClosure RestProxyCallAsyncClosure; +typedef struct _RestProxyCallContinuousClosure RestProxyCallContinuousClosure; struct _RestProxyCallPrivate { gchar *method; diff --git a/rest/rest-proxy-call.c b/rest/rest-proxy-call.c index 007fd25..c90c75b 100644 --- a/rest/rest-proxy-call.c +++ b/rest/rest-proxy-call.c @@ -41,6 +41,15 @@ struct _RestProxyCallAsyncClosure { SoupMessage *message; }; + +struct _RestProxyCallContinuousClosure { + RestProxyCall *call; + RestProxyCallContinuousCallback callback; + GObject *weak_object; + gpointer userdata; + SoupMessage *message; +}; + enum { PROP_0 = 0, @@ -627,6 +636,49 @@ _call_message_completed_cb (SoupSession *session, g_slice_free (RestProxyCallAsyncClosure, closure); } + +static void +_continuous_call_message_completed_cb (SoupSession *session, + SoupMessage *message, + gpointer userdata) +{ + RestProxyCallContinuousClosure *closure; + RestProxyCall *call; + RestProxyCallPrivate *priv; + GError *error = NULL; + + closure = (RestProxyCallContinuousClosure *)userdata; + call = closure->call; + priv = GET_PRIVATE (call); + + priv->status_code = message->status_code; + priv->status_message = g_strdup (message->reason_phrase); + + _handle_error_from_message (message, &error); + + closure->callback (closure->call, + NULL, + 0, + error, + closure->weak_object, + closure->userdata); + + g_clear_error (&error); + + /* Success. We don't need the weak reference any more */ + if (closure->weak_object) + { + g_object_weak_unref (closure->weak_object, + (GWeakNotify)_call_async_weak_notify_cb, + closure); + } + + priv->cur_call_closure = NULL; + g_object_unref (closure->call); + g_slice_free (RestProxyCallContinuousClosure, closure); +} + + static void _call_async_weak_notify_cb (gpointer *data, GObject *dead_object) @@ -818,6 +870,83 @@ error: return FALSE; } +static void +_continuous_call_message_got_chunk_cb (SoupMessage *msg, + SoupBuffer *chunk, + RestProxyCallContinuousClosure *closure) +{ + closure->callback (closure->call, + chunk->data, + chunk->length, + NULL, + closure->weak_object, + closure->userdata); +} + +gboolean +rest_proxy_call_continuous (RestProxyCall *call, + RestProxyCallContinuousCallback callback, + GObject *weak_object, + gpointer userdata, + GError **error) +{ + RestProxyCallPrivate *priv; + RestProxyCallClass *call_class; + SoupMessage *message; + RestProxyCallContinuousClosure *closure; + + g_return_val_if_fail (REST_IS_PROXY_CALL (call), FALSE); + priv = GET_PRIVATE (call); + g_assert (priv->proxy); + call_class = REST_PROXY_CALL_GET_CLASS (call); + + if (priv->cur_call_closure) + { + /* FIXME: Use GError here */ + g_critical (G_STRLOC ": Call already in progress."); + return FALSE; + } + + message = prepare_message (call, error); + if (message == NULL) + goto error; + + closure = g_slice_new0 (RestProxyCallContinuousClosure); + closure->call = g_object_ref (call); + closure->callback = callback; + closure->weak_object = weak_object; + closure->message = message; + closure->userdata = userdata; + + priv->cur_call_closure = closure; + + /* Weakly reference this object. We remove our callback if it goes away. */ + if (closure->weak_object) + { + g_object_weak_ref (closure->weak_object, + (GWeakNotify)_call_async_weak_notify_cb, + closure); + } + + g_signal_connect (message, + "got-chunk", + (GCallback)_continuous_call_message_got_chunk_cb, + closure); + + _rest_proxy_queue_message (priv->proxy, + message, + _continuous_call_message_completed_cb, + closure); + g_free (priv->url); + priv->url = NULL; + return TRUE; + +error: + g_free (priv->url); + priv->url = NULL; + return FALSE; +} + /** * rest_proxy_call_cancel: * @call: The #RestProxyCall diff --git a/rest/rest-proxy-call.h b/rest/rest-proxy-call.h index c9648b2..6f65914 100644 --- a/rest/rest-proxy-call.h +++ b/rest/rest-proxy-call.h @@ -155,6 +155,20 @@ gboolean rest_proxy_call_async (RestProxyCall *call, gpointer userdata, GError **error); + +typedef void (*RestProxyCallContinuousCallback) (RestProxyCall *call, + const gchar *buf, + gsize len, + const GError *error, + GObject *weak_object, + gpointer userdata); + +gboolean rest_proxy_call_continuous (RestProxyCall *call, + RestProxyCallContinuousCallback cb, + GObject *weak_object, + gpointer userdata, + GError **error); + gboolean rest_proxy_call_cancel (RestProxyCall *call); gboolean rest_proxy_call_sync (RestProxyCall *call, GError **error_out); |