From 3ef91e1f671f02f0034446e1ca78532259fb6dbb Mon Sep 17 00:00:00 2001 From: Alex Graveley Date: Thu, 7 Jun 2001 00:50:23 +0000 Subject: [PATCH] implement. (soup_message_add_response_code_handler): ditto. 2001-06-06 Alex Graveley * src/soup-core/soup-message.c (soup_message_add_header_handler): implement. (soup_message_add_response_code_handler): ditto. (soup_message_add_body_handler): ditto. (soup_message_run_handlers): uh-huh. (soup_message_free): Free allocated handler info. * src/soup-core/soup-message.h: Change SOUP_MESSAGE_PROCESS_CHUNKS to SOUP_MESSAGE_OVERWRITE_CHUNKS. This will allow large files to be processed using a BODY_CHUNK handler, instead of keeping everything in memory. * src/soup-core/soup-queue.c (soup_process_headers): Run PRE_BODY handlers. (soup_finish_read): Run POST_BODY handlers. (soup_queue_read_cb): Run BODY_CHUNK handlers. --- ChangeLog | 19 ++++++++ libsoup/soup-message.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++--- libsoup/soup-message.h | 8 ++-- libsoup/soup-private.h | 2 + libsoup/soup-queue.c | 25 ++++++++++- 5 files changed, 157 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 091b2f4..902fd8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2001-06-06 Alex Graveley + + * src/soup-core/soup-message.c (soup_message_add_header_handler): + implement. + (soup_message_add_response_code_handler): ditto. + (soup_message_add_body_handler): ditto. + (soup_message_run_handlers): uh-huh. + (soup_message_free): Free allocated handler info. + + * src/soup-core/soup-message.h: Change SOUP_MESSAGE_PROCESS_CHUNKS + to SOUP_MESSAGE_OVERWRITE_CHUNKS. This will allow large files to + be processed using a BODY_CHUNK handler, instead of keeping + everything in memory. + + * src/soup-core/soup-queue.c (soup_process_headers): Run PRE_BODY + handlers. + (soup_finish_read): Run POST_BODY handlers. + (soup_queue_read_cb): Run BODY_CHUNK handlers. + 2001-06-06 Joe Shaw * src/soup-core/soup-message.c (soup_message_set_method, diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 28170de..badea47 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -161,6 +161,9 @@ soup_message_free (SoupMessage *req) g_hash_table_destroy (req->response_headers); } + g_slist_foreach (req->priv->content_handlers, (GFunc) g_free, NULL); + g_slist_free (req->priv->content_handlers); + g_free (req->priv); g_free (req->action); g_free (req); @@ -358,8 +361,8 @@ soup_message_get_flags (SoupMessage *msg) void soup_message_set_method (SoupMessage *msg, const gchar *method) { - g_return_if_fail(msg); - g_return_if_fail(method); + g_return_if_fail (msg != NULL); + g_return_if_fail (method != NULL); msg->method = method; } @@ -367,11 +370,50 @@ soup_message_set_method (SoupMessage *msg, const gchar *method) const gchar * soup_message_get_method (SoupMessage *msg) { - g_return_val_if_fail(msg, NULL); + g_return_val_if_fail (msg != NULL, NULL); return msg->method; } +typedef enum { + RESPONSE_HEADER_HANDLER, + RESPONSE_CODE_HANDLER, + RESPONSE_BODY_HANDLER +} SoupHandlerKind; + +typedef struct { + SoupHandlerType type; + SoupHandlerFn handler_cb; + gpointer user_data; + + SoupHandlerKind kind; + const gchar *header; + guint code; +} SoupHandlerData; + +static void +soup_message_add_handler (SoupMessage *msg, + SoupHandlerType type, + SoupHandlerFn handler_cb, + gpointer user_data, + SoupHandlerKind kind, + const gchar *header, + guint code) +{ + SoupHandlerData *data; + + data = g_new0 (SoupHandlerData, 1); + data->type = type; + data->handler_cb = handler_cb; + data->user_data = user_data; + data->kind = kind; + data->header = header; + data->code = code; + + msg->priv->content_handlers = + g_slist_append (msg->priv->content_handlers, data); +} + void soup_message_add_header_handler (SoupMessage *msg, const gchar *header, @@ -379,7 +421,17 @@ soup_message_add_header_handler (SoupMessage *msg, SoupHandlerFn handler_cb, gpointer user_data) { - g_warning ("Not yet implemented."); + g_return_if_fail (msg != NULL); + g_return_if_fail (header != NULL); + g_return_if_fail (handler_cb != NULL); + + soup_message_add_handler (msg, + type, + handler_cb, + user_data, + RESPONSE_HEADER_HANDLER, + header, + 0); } void @@ -389,7 +441,17 @@ soup_message_add_response_code_handler (SoupMessage *msg, SoupHandlerFn handler_cb, gpointer user_data) { - g_warning ("Not yet implemented."); + g_return_if_fail (msg != NULL); + g_return_if_fail (code != 0); + g_return_if_fail (handler_cb != NULL); + + soup_message_add_handler (msg, + type, + handler_cb, + user_data, + RESPONSE_CODE_HANDLER, + NULL, + code); } void @@ -398,5 +460,46 @@ soup_message_add_body_handler (SoupMessage *msg, SoupHandlerFn handler_cb, gpointer user_data) { - g_warning ("Not yet implemented."); + g_return_if_fail (msg != NULL); + g_return_if_fail (handler_cb != NULL); + + soup_message_add_handler (msg, + type, + handler_cb, + user_data, + RESPONSE_BODY_HANDLER, + NULL, + 0); +} + +SoupErrorCode +soup_message_run_handlers (SoupMessage *msg, SoupHandlerType invoke_type) +{ + GSList *list; + SoupErrorCode retval = SOUP_ERROR_NONE; + + g_return_val_if_fail (msg != NULL, retval); + + for (list = msg->priv->content_handlers; list; list = list->next) { + SoupHandlerData *data = list->data; + + if (data->type != invoke_type) continue; + + switch (data->kind) { + case RESPONSE_HEADER_HANDLER: + if (!soup_message_get_response_header (msg, + data->header)) + continue; + break; + case RESPONSE_CODE_HANDLER: + if (msg->response_code != data->code) continue; + break; + } + + retval = (*data->handler_cb) (msg, data->user_data); + + if (retval != SOUP_ERROR_NONE) break; + } + + return retval; } diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h index 6e744a3..462776e 100644 --- a/libsoup/soup-message.h +++ b/libsoup/soup-message.h @@ -123,7 +123,7 @@ typedef enum { SOUP_HANDLER_POST_BODY } SoupHandlerType; -typedef SoupErrorCode SoupHandlerFn (SoupMessage *msg, gpointer user_data); +typedef SoupErrorCode (*SoupHandlerFn) (SoupMessage *msg, gpointer user_data); void soup_message_add_header_handler (SoupMessage *msg, const gchar *header, @@ -145,9 +145,9 @@ void soup_message_add_body_handler (SoupMessage *msg, /* FIXME: None of these are implemented yet, oh well... */ typedef enum { - SOUP_MESSAGE_FOLLOW_REDIRECT = (1 << 1), - SOUP_MESSAGE_NO_COOKIE = (1 << 2), - SOUP_MESSAGE_PROCESS_CHUNKS = (1 << 3) + SOUP_MESSAGE_FOLLOW_REDIRECT = (1 << 1), + SOUP_MESSAGE_NO_COOKIE = (1 << 2), + SOUP_MESSAGE_OVERWRITE_CHUNKS = (1 << 3) } SoupMessageFlags; void soup_message_set_flags (SoupMessage *msg, diff --git a/libsoup/soup-private.h b/libsoup/soup-private.h index 311d0e8..73ba00b 100644 --- a/libsoup/soup-private.h +++ b/libsoup/soup-private.h @@ -99,6 +99,8 @@ struct _SoupMessagePrivate { gpointer digest_data; guint msg_flags; + + GSList *content_handlers; }; typedef struct { diff --git a/libsoup/soup-queue.c b/libsoup/soup-queue.c index 499a557..4016f41 100644 --- a/libsoup/soup-queue.c +++ b/libsoup/soup-queue.c @@ -73,6 +73,7 @@ static gboolean soup_process_headers (SoupMessage *req) { gchar *connection, *length, *enc; + SoupErrorCode err = SOUP_ERROR_MALFORMED_HEADER; /* Handle connection persistence */ connection = g_hash_table_lookup (req->response_headers, "Connection"); @@ -95,10 +96,13 @@ soup_process_headers (SoupMessage *req) } } + err = soup_message_run_handlers (req, SOUP_HANDLER_PRE_BODY); + if (err) goto THROW_MALFORMED_HEADER; + return TRUE; THROW_MALFORMED_HEADER: - soup_message_issue_callback (req, SOUP_ERROR_MALFORMED_HEADER); + soup_message_issue_callback (req, err); return FALSE; } @@ -183,6 +187,7 @@ soup_finish_read (SoupMessage *req) { GByteArray *arr = req->priv->recv_buf; gint index = req->priv->header_len; + SoupErrorCode err; req->response.owner = SOUP_BUFFER_SYSTEM_OWNED; req->response.length = arr->len - index ; @@ -194,7 +199,13 @@ soup_finish_read (SoupMessage *req) req->priv->recv_buf = NULL; req->status = SOUP_STATUS_FINISHED; - soup_message_issue_callback (req, SOUP_ERROR_NONE); + + err = soup_message_run_handlers (req, SOUP_HANDLER_POST_BODY); + + if (err) + soup_message_issue_callback (req, err); + else + soup_message_issue_callback (req, SOUP_ERROR_NONE); } static gboolean @@ -208,6 +219,7 @@ soup_queue_read_cb (GIOChannel* iochannel, gint index = req->priv->header_len; GByteArray *arr = req->priv->recv_buf; GIOError error; + SoupErrorCode err; error = g_io_channel_read (iochannel, read_buf, @@ -239,6 +251,15 @@ soup_queue_read_cb (GIOChannel* iochannel, return FALSE; } + /* Don't call chunk handlers if we didn't actually read anything */ + if (bytes_read != 0) { + err = soup_message_run_handlers (req, SOUP_HANDLER_BODY_CHUNK); + if (err) { + soup_message_issue_callback (req, err); + return FALSE; + } + } + if (bytes_read == 0) read_done = TRUE; else if (req->priv->is_chunked) read_done = soup_read_chunk (req); else if (req->priv->content_length==arr->len-index-4) read_done = TRUE; -- 2.7.4