summaryrefslogtreecommitdiff
path: root/libsoup/soup-message-body.c
diff options
context:
space:
mode:
authorDan Winship <danw@src.gnome.org>2008-04-05 19:35:35 +0000
committerDan Winship <danw@src.gnome.org>2008-04-05 19:35:35 +0000
commit797462000d2e977db154d3eae120a308f18a8085 (patch)
treed80a3ae1ef6c2247e6e253246820aa559742c184 /libsoup/soup-message-body.c
parent69bac3aac055b260f3ba0590f05a35298fb33908 (diff)
downloadlibsoup-797462000d2e977db154d3eae120a308f18a8085.tar.gz
New, replaces SOUP_MESSAGE_OVERWRITE_CHUNKS, but can be set on either the
* libsoup/soup-message-body.c (soup_message_body_set_accumulate) (soup_message_body_get_accumulate): New, replaces SOUP_MESSAGE_OVERWRITE_CHUNKS, but can be set on either the incoming or outgoing message body. (soup_message_body_get_chunk): update to still dtrt if !accumulate (soup_message_body_got_chunk, soup_message_body_wrote_chunk): New methods to handle accumulating/discarding chunks. * libsoup/soup-message-io.c (read_body_chunk): Use soup_message_body_got_chunk. (io_write): Use soup_message_body_wrote_chunk, to discard unneeded chunks after writing them. Fixes most of #522146. * libsoup/soup-message.c (soup_message_class_init): add a new flag, "server-side", to indicate whether the message is client-side or server-side, and update several methods to use it. (got_body): Update for accumulate (soup_message_set_flags): If the caller changes OVERWRITE_CHUNKS, update the corresponding accumulate flag. * libsoup/soup-message.h (SOUP_MESSAGE_OVERWRITE_CHUNKS): deprecated now * tests/chunk-test.c (do_request_test): Use soup_message_body_set_accumulate() now, and verify that the chunks are being discarded appropriately. (do_response_test): Use soup_message_body_set_accumulate() instead of OVERWRITE_CHUNKS. * tests/pull-api.c (do_fully_async_test) (do_synchronously_async_test): Use soup_message_body_set_accumulate(). svn path=/trunk/; revision=1126
Diffstat (limited to 'libsoup/soup-message-body.c')
-rw-r--r--libsoup/soup-message-body.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/libsoup/soup-message-body.c b/libsoup/soup-message-body.c
index de8ac801..f83b883f 100644
--- a/libsoup/soup-message-body.c
+++ b/libsoup/soup-message-body.c
@@ -304,6 +304,8 @@ typedef struct {
SoupMessageBody body;
GSList *chunks, *last;
SoupBuffer *flattened;
+ gboolean accumulate;
+ goffset base_offset;
int ref_count;
} SoupMessageBodyPrivate;
@@ -321,11 +323,63 @@ soup_message_body_new (void)
SoupMessageBodyPrivate *priv;
priv = g_slice_new0 (SoupMessageBodyPrivate);
+ priv->accumulate = TRUE;
priv->ref_count = 1;
return (SoupMessageBody *)priv;
}
+/**
+ * soup_message_body_set_accumulate:
+ * @body: a #SoupMessageBody
+ * @accumulate: whether or not to accumulate body chunks in @body
+ *
+ * Sets or clears the accumulate flag on @body. (The default value
+ * is %TRUE.)
+ *
+ * If you set this flag to %FALSE on an "incoming" message body (that
+ * is, the %response_body of a client-side message, or %request_body
+ * of a server-side message), this will cause each chunk of the body
+ * to be discarded after its corresponding #SoupMessage::got_chunk
+ * signal is emitted. (This is equivalent to setting the deprecated
+ * %SOUP_MESSAGE_OVERWRITE_CHUNKS flag on the message.)
+ *
+ * If you set this flag to %FALSE on an "outgoing" message body (the
+ * %request_body of a client-side message, or %response_body of a
+ * server-side message), it will cause each chunk of the body to be
+ * discarded after its corresponding #SoupMessage::wrote_chunk signal
+ * is emitted.
+ *
+ * In either case, @body's %data field will not be filled in after the
+ * body is fully sent/received, since the body data will no longer be
+ * available
+ **/
+void
+soup_message_body_set_accumulate (SoupMessageBody *body,
+ gboolean accumulate)
+{
+ SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
+
+ priv->accumulate = accumulate;
+}
+
+/**
+ * soup_message_body_get_accumulate:
+ * @body: a #SoupMessageBody
+ *
+ * Gets the accumulate flag on @body; see
+ * soup_message_body_set_accumulate() for details.
+ *
+ * Return value: the accumulate flag for @body.
+ **/
+gboolean
+soup_message_body_get_accumulate (SoupMessageBody *body)
+{
+ SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
+
+ return priv->accumulate;
+}
+
static void
append_buffer (SoupMessageBody *body, SoupBuffer *buffer)
{
@@ -438,6 +492,8 @@ soup_message_body_flatten (SoupMessageBody *body)
GSList *iter;
SoupBuffer *chunk;
+ g_return_val_if_fail (priv->accumulate == TRUE, NULL);
+
if (!priv->flattened) {
#if GLIB_SIZEOF_SIZE_T < 8
g_return_val_if_fail (body->length < G_MAXSIZE, NULL);
@@ -489,6 +545,7 @@ soup_message_body_get_chunk (SoupMessageBody *body, goffset offset)
GSList *iter;
SoupBuffer *chunk = NULL;
+ offset -= priv->base_offset;
for (iter = priv->chunks; iter; iter = iter->next) {
chunk = iter->data;
@@ -509,6 +566,63 @@ soup_message_body_get_chunk (SoupMessageBody *body, goffset offset)
}
}
+/**
+ * soup_message_body_got_chunk:
+ * @body: a #SoupMessageBody
+ * @chunk: a #SoupBuffer received from the network
+ *
+ * Handles the #SoupMessageBody part of receiving a chunk of data from
+ * the network. Normally this means appending @chunk to @body, exactly
+ * as with soup_message_body_append_buffer(), but if you have set
+ * @body's accumulate flag to %FALSE, then that will not happen.
+ *
+ * This is a low-level method which you should not normally need to
+ * use.
+ **/
+void
+soup_message_body_got_chunk (SoupMessageBody *body, SoupBuffer *chunk)
+{
+ SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
+
+ if (!priv->accumulate)
+ return;
+
+ soup_message_body_append_buffer (body, chunk);
+}
+
+/**
+ * soup_message_body_wrote_chunk:
+ * @body: a #SoupMessageBody
+ * @chunk: a #SoupBuffer received from the network
+ *
+ * Handles the #SoupMessageBody part of writing a chunk of data to the
+ * network. Normally this is a no-op, but if you have set @body's
+ * accumulate flag to %FALSE, then this will cause @chunk (and any
+ * chunks preceding it in @body) to be discarded to free up memory.
+ *
+ * This is a low-level method which you should not normally need to
+ * use.
+ **/
+void
+soup_message_body_wrote_chunk (SoupMessageBody *body, SoupBuffer *chunk)
+{
+ SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
+ SoupBuffer *chunk2;
+
+ if (priv->accumulate)
+ return;
+
+ do {
+ chunk2 = priv->chunks->data;
+ priv->chunks = g_slist_remove (priv->chunks, chunk2);
+ priv->base_offset += chunk2->length;
+ soup_buffer_free (chunk2);
+ } while (priv->chunks && chunk2 != chunk);
+
+ if (!priv->chunks)
+ priv->last = NULL;
+}
+
static SoupMessageBody *
soup_message_body_copy (SoupMessageBody *body)
{