Update to call renamed SoupHandlerEvents.
authorAlex Graveley <alex@ximian.com>
Fri, 9 Nov 2001 01:38:52 +0000 (01:38 +0000)
committerAlex Graveley <orph@src.gnome.org>
Fri, 9 Nov 2001 01:38:52 +0000 (01:38 +0000)
2001-11-08  Alex Graveley  <alex@ximian.com>

* src/libsoup/soup-queue.c (soup_queue_read_headers_cb):
(soup_queue_read_chunk_cb):
(soup_queue_read_done_cb): Update to call renamed SoupHandlerEvents.

* src/libsoup/soup-message.[ch]: Remove
soup_message_get_request_header, soup_message_set_request_header,
soup_message_get_response_header,
soup_message_set_response_header,
soup_message_add_error_code_handler,
soup_message_add_error_class_handler,
soup_message_add_header_handler.
(redirect_handler): Update for new handler interface.
(authorize_handler): Ditto.
(timeout_handler): Impl.
(soup_message_remove_handler): Impl.
(soup_message_remove_handler_by_func): Impl.
(soup_message_remove_handler_by_func_and_data): Impl.
(soup_message_list_handlers): Impl.

ChangeLog
libsoup/soup-message.c
libsoup/soup-message.h
libsoup/soup-private.h
libsoup/soup-queue.c

index ad7cd0f..7dd4164 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,26 @@
 2001-11-08  Alex Graveley  <alex@ximian.com>
 
+       * src/libsoup/soup-queue.c (soup_queue_read_headers_cb): 
+       (soup_queue_read_chunk_cb): 
+       (soup_queue_read_done_cb): Update to call renamed SoupHandlerEvents.
+
+       * src/libsoup/soup-message.[ch]: Remove
+       soup_message_get_request_header, soup_message_set_request_header,
+       soup_message_get_response_header,
+       soup_message_set_response_header,
+       soup_message_add_error_code_handler,
+       soup_message_add_error_class_handler,
+       soup_message_add_header_handler.
+       (redirect_handler): Update for new handler interface.
+       (authorize_handler): Ditto.
+       (timeout_handler): Impl.
+       (soup_message_remove_handler): Impl.
+       (soup_message_remove_handler_by_func): Impl.
+       (soup_message_remove_handler_by_func_and_data): Impl.
+       (soup_message_list_handlers): Impl.
+
+2001-11-08  Alex Graveley  <alex@ximian.com>
+
        * configure.in: Bump HEAD version to 0.6.99.
        * src/libsoup/soup-private.h (VERSION): Ditto.
 
index 1e9fa7a..3eb0b38 100644 (file)
 #include "soup-queue.h"
 #include "soup-transfer.h"
 
+typedef struct {
+       SoupHandlerEvent   type;
+       gchar             *name;
+       SoupHandlerWhen    order;
+       SoupHandlerFilter  filter;
+       SoupHandlerFn      handler_cb;
+       gpointer           user_data;
+
+       SoupMessage       *msg; 
+       guint              timeout_tag;
+} SoupHandlerData;
+
 /**
  * soup_message_new:
  * @context: a %SoupContext for the destination endpoint.
@@ -126,6 +138,22 @@ soup_message_cleanup (SoupMessage *req)
 }
 
 static void
+handler_free (SoupHandlerData *data)
+{
+       if (data->filter.type == SOUP_FILTER_HEADER)
+               g_free ((gchar *) data->filter.data.header);
+
+       if (data->timeout_tag)
+               g_source_remove (data->timeout_tag);
+
+       data->msg->priv->content_handlers = 
+               g_slist_remove (data->msg->priv->content_handlers, data);
+
+       g_free (data->name);
+       g_free (data);
+}
+
+static void
 finalize_message (SoupMessage *req)
 {
        soup_context_unref (req->context);
@@ -144,8 +172,10 @@ finalize_message (SoupMessage *req)
        soup_message_clear_headers (req->response_headers);
        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);
+       while (req->priv->content_handlers) {
+               SoupHandlerData *data = req->priv->content_handlers->data;
+               handler_free (data);
+       }
 
        g_free ((gchar *) req->errorphrase);
        g_free (req->priv);
@@ -404,122 +434,6 @@ soup_message_foreach_remove_header (GHashTable        *hash,
 }
 
 /**
- * soup_message_set_request_header:
- * @req: a %SoupMessage.
- * @name: header name.
- * @value: header value.
- *
- * ** DEPRECATED **
- * 
- * Adds a new transport header to be sent on an outgoing request. Passing a NULL
- * @value will remove all headers with a name equal to @name.
- */
-void
-soup_message_set_request_header (SoupMessage *req,
-                                const gchar *name,
-                                const gchar *value) 
-{
-       g_return_if_fail (req != NULL);
-       g_return_if_fail (name != NULL || name [0] != '\0');
-
-       g_warning ("soup_message_set_request_header is DEPRECATED. Use "
-                  "soup_message_add_header, with msg->request_headers as "
-                  "the first argument.\n");
-
-       soup_message_add_header (req->request_headers, name, value);
-}
-
-/**
- * soup_message_get_request_header:
- * @req: a %SoupMessage.
- * @name: header name.
- * 
- * ** DEPRECATED **
- * 
- * Lookup the first transport request header with a key equal to @name.
- *
- * Return value: the header's value or NULL if not found.
- */
-const gchar *
-soup_message_get_request_header (SoupMessage *req,
-                                const gchar *name) 
-{
-       GSList *vals;
-       g_return_val_if_fail (req != NULL, NULL);
-       g_return_val_if_fail (name != NULL || name [0] != '\0', NULL);
-
-       g_warning ("soup_message_get_request_header is DEPRECATED. Use "
-                  "soup_message_get_header, with msg->request_headers as "
-                  "the first argument.\n");
-
-       if (req->request_headers) {
-               vals = g_hash_table_lookup (req->request_headers, name);
-               if (vals) 
-                       return vals->data;
-       }
-
-       return NULL;
-}
-
-/**
- * soup_message_set_response_header:
- * @req: a %SoupMessage.
- * @name: header name.
- * @value: header value.
- * 
- * ** DEPRECATED **
- * 
- * Adds a new transport header to be sent on an outgoing response. Passing a
- * NULL @value will remove all headers with a name equal to @name.
- */
-void
-soup_message_set_response_header (SoupMessage *req,
-                                 const gchar *name,
-                                 const gchar *value) 
-{
-       g_return_if_fail (req != NULL);
-       g_return_if_fail (name != NULL || name [0] != '\0');
-
-       g_warning ("soup_message_set_response_header is DEPRECATED. Use "
-                  "soup_message_add_header, with msg->response_headers as "
-                  "the first argument.\n");
-
-       soup_message_add_header (req->response_headers, name, value);
-}
-
-/**
- * soup_message_get_response_header:
- * @req: a %SoupMessage.
- * @name: header name.
- * 
- * ** DEPRECATED **
- * 
- * Lookup the transport response header with a key equal to @name.
- *
- * Return value: the header's value or NULL if not found.
- */
-const gchar *
-soup_message_get_response_header (SoupMessage *req,
-                                 const gchar *name) 
-{
-       GSList *vals;
-       g_return_val_if_fail (req != NULL, NULL);
-       g_return_val_if_fail (name != NULL || name [0] != '\0', NULL);
-
-       g_warning ("soup_message_get_response_header is DEPRECATED. Use "
-                  "soup_message_get_header, with msg->response_headers as "
-                  "the first argument.\n");
-
-       if (req->response_headers) {
-               vals = g_hash_table_lookup (req->response_headers, name);
-               if (vals) 
-                       return vals->data;
-       }
-
-       return NULL;
-}
-
-/**
  * soup_message_queue:
  * @req: a %SoupMessage.
  * @callback: a %SoupCallbackFn which will be called after the message completes
@@ -574,9 +488,10 @@ soup_message_send (SoupMessage *msg)
        return msg->errorclass;
 }
 
-static void 
-authorize_handler (SoupMessage *msg, gboolean proxy)
+static SoupHandlerResult 
+authorize_handler (SoupMessage *msg, gpointer user_data)
 {
+       gboolean proxy = GPOINTER_TO_INT (user_data);
        const GSList *vals;
        SoupAuth *auth, *old_auth;
        SoupContext *ctx;
@@ -602,7 +517,7 @@ authorize_handler (SoupMessage *msg, gboolean proxy)
                                "Unknown authentication scheme required by "
                                "proxy" :
                                "Unknown authentication scheme required");
-               return;
+               return SOUP_HANDLER_RESTART;
        }
 
        /*
@@ -634,24 +549,24 @@ authorize_handler (SoupMessage *msg, gboolean proxy)
 
        soup_auth_set_context (auth, ctx);
 
-       soup_message_queue (msg, msg->priv->callback, msg->priv->user_data);
-
-        return;
+        return SOUP_HANDLER_RESEND;
 
  THROW_CANT_AUTHENTICATE:
        soup_message_set_error (msg, 
                                proxy ? 
                                        SOUP_ERROR_CANT_AUTHENTICATE_PROXY : 
                                        SOUP_ERROR_CANT_AUTHENTICATE);
+       return SOUP_HANDLER_RESTART;
 }
 
-static void 
+static SoupHandlerResult  
 redirect_handler (SoupMessage *msg, gpointer user_data)
 {
        const gchar *new_loc;
 
        if (msg->errorclass != SOUP_ERROR_CLASS_REDIRECT || 
-           msg->priv->msg_flags & SOUP_MESSAGE_NO_REDIRECT) return;
+           msg->priv->msg_flags & SOUP_MESSAGE_NO_REDIRECT) 
+               return SOUP_HANDLER_CONTINUE;
 
        new_loc = soup_message_get_header (msg->response_headers, "Location");
 
@@ -685,98 +600,141 @@ redirect_handler (SoupMessage *msg, gpointer user_data)
                soup_message_set_context (msg, new_ctx);
                soup_context_unref (new_ctx);
 
-               soup_message_queue (msg,
-                                   msg->priv->callback, 
-                                   msg->priv->user_data);
+               return SOUP_HANDLER_RESEND;
        }
 
-       return;
+       return SOUP_HANDLER_CONTINUE;
 
  INVALID_REDIRECT:
        soup_message_set_error_full (msg, 
                                     SOUP_ERROR_MALFORMED,
                                     "Invalid Redirect URL");
+       return SOUP_HANDLER_RESTART;
 }
 
-typedef enum {
-       RESPONSE_HEADER_HANDLER = 1,
-       RESPONSE_ERROR_CODE_HANDLER,
-       RESPONSE_ERROR_CLASS_HANDLER
-} SoupHandlerKind;
-
-typedef struct {
-       SoupHandlerType   type;
-       SoupCallbackFn    handler_cb;
-       gpointer          user_data;
-
-       SoupHandlerKind   kind;
-       union {
-               guint             errorcode;
-               SoupErrorClass    errorclass;
-               const gchar      *header;
-       } data;
-} SoupHandlerData;
-
 static SoupHandlerData global_handlers [] = {
        /* 
         * Handle redirect response codes 300, 301, 302, 303, and 305.
         */
        {
-               SOUP_HANDLER_PRE_BODY,
+               SOUP_HANDLER_HEADERS,
+               "redirect",
+               0,
+               { 
+                       SOUP_FILTER_HEADER,
+                       {
+                               (guint) "Location"
+                       },
+               },
                redirect_handler, 
                NULL, 
-               RESPONSE_HEADER_HANDLER, 
-               { (guint) "Location" }
        },
        /* 
         * Handle authorization.
         */
        {
-               SOUP_HANDLER_PRE_BODY,
-               (SoupCallbackFn) authorize_handler, 
+               SOUP_HANDLER_HEADERS,
+               "authenticate",
+               0,
+               { 
+                       SOUP_FILTER_ERROR_CODE,
+                       {
+                               401
+                       },
+               },
+               authorize_handler, 
                GINT_TO_POINTER (FALSE), 
-               RESPONSE_ERROR_CODE_HANDLER, 
-               { 401 }
        },
        /* 
         * Handle proxy authorization.
         */
        {
-               SOUP_HANDLER_PRE_BODY,
-               (SoupCallbackFn) authorize_handler, 
+               SOUP_HANDLER_HEADERS,
+               "proxy-authenticate",
+               0,
+               { 
+                       SOUP_FILTER_ERROR_CODE,
+                       {
+                               407
+                       },
+               },
+               authorize_handler, 
                GINT_TO_POINTER (TRUE), 
-               RESPONSE_ERROR_CODE_HANDLER, 
-               { 407 }
        },
        { 0 }
 };
 
-static inline void 
-run_handler (SoupMessage     *msg, 
-            SoupHandlerType  invoke_type, 
-            SoupHandlerData *data)
+static inline SoupHandlerResult 
+run_handler (SoupMessage      *msg, 
+            SoupHandlerEvent  invoke_type, 
+            SoupHandlerEvent  when, 
+            SoupHandlerData  *data)
 {
-       if (data->type != invoke_type) return;
+       SoupHandlerResult result;
 
-       switch (data->kind) {
-       case RESPONSE_HEADER_HANDLER:
+       if (data->type != invoke_type || data->order != when) 
+               return SOUP_HANDLER_CONTINUE;
+
+       switch (data->filter.type) {
+       case SOUP_FILTER_HEADER:
                if (!soup_message_get_header (msg->response_headers,
-                                             data->data.header))
-                       return;
+                                             data->filter.data.header))
+                       return SOUP_HANDLER_CONTINUE;
                break;
-       case RESPONSE_ERROR_CODE_HANDLER:
-               if (msg->errorcode != data->data.errorcode) return;
+       case SOUP_FILTER_ERROR_CODE:
+               if (msg->errorcode != data->filter.data.errorcode) 
+                       return SOUP_HANDLER_CONTINUE;
                break;
-       case RESPONSE_ERROR_CLASS_HANDLER:
-               if (msg->errorclass != data->data.errorclass) return;
+       case SOUP_FILTER_ERROR_CLASS:
+               if (msg->errorclass != data->filter.data.errorclass) 
+                       return SOUP_HANDLER_CONTINUE;
                break;
+       case SOUP_FILTER_TIMEOUT:
+               return SOUP_HANDLER_CONTINUE;
        default:
                break;
        }
 
-       (*data->handler_cb) (msg, data->user_data);
+       result = (*data->handler_cb) (msg, data->user_data);
+
+       switch (result) {
+       case SOUP_HANDLER_STOP:
+               if (invoke_type == SOUP_HANDLER_FINISHED && 
+                   msg->errorclass != SOUP_ERROR_CLASS_INFORMATIONAL)
+                       soup_message_issue_callback (msg);
+               break;
+       case SOUP_HANDLER_KILL:
+               soup_message_issue_callback (msg);
+               break;
+       case SOUP_HANDLER_RESEND:
+               if (msg->status != SOUP_STATUS_QUEUED)
+                       soup_message_queue (msg,
+                                           msg->priv->callback,
+                                           msg->priv->user_data);
+               break;
+       default:
+               if (msg->status == SOUP_STATUS_QUEUED)
+                       result = SOUP_HANDLER_RESEND;
+               break;
+       }
+
+       return result;
 }
 
+#define PROCESS_HANDLER_RESULT(result) ({ \
+       switch (result) {                 \
+       case SOUP_HANDLER_STOP:           \
+               return FALSE;             \
+       case SOUP_HANDLER_KILL:           \
+       case SOUP_HANDLER_RESEND:         \
+               return TRUE;              \
+       case SOUP_HANDLER_RESTART:        \
+               goto RESTART;             \
+       default:                          \
+               break;                    \
+       }                                 \
+})
+
 /*
  * Run each handler with matching criteria (first per-message then global
  * handlers). If a handler requeues a message, we stop processing and terminate
@@ -789,32 +747,55 @@ run_handler (SoupMessage     *msg,
  * processing.  
  */
 gboolean
-soup_message_run_handlers (SoupMessage *msg, SoupHandlerType invoke_type)
+soup_message_run_handlers (SoupMessage *msg, SoupHandlerEvent invoke_type)
 {
        GSList *list;
        SoupHandlerData *data;
+       SoupHandlerResult result;
 
        g_return_val_if_fail (msg != NULL, FALSE);
 
+ RESTART:
+       /*
+        * Pre-Global handlers
+        */
        for (list = msg->priv->content_handlers; list; list = list->next) {
                data = list->data;
-
-               run_handler (msg, invoke_type, data);
-
-               if (msg->status == SOUP_STATUS_QUEUED) return TRUE;
+               result = run_handler (msg, 
+                                     invoke_type, 
+                                     SOUP_HANDLER_FIRST, 
+                                     data);
+               PROCESS_HANDLER_RESULT (result);
        }
 
+       /*
+        * Global handlers
+        */
        for (data = global_handlers; data->type; data++) {
-               run_handler (msg, invoke_type, data);
+               result = run_handler (msg, 
+                                     invoke_type, 
+                                     0, 
+                                     data);
+               PROCESS_HANDLER_RESULT (result);
+       }
 
-               if (msg->status == SOUP_STATUS_QUEUED) return TRUE;
+       /*
+        * Post-Global handlers
+        */
+       for (list = msg->priv->content_handlers; list; list = list->next) {
+               data = list->data;
+               result = run_handler (msg, 
+                                     invoke_type, 
+                                     SOUP_HANDLER_LAST, 
+                                     data);
+               PROCESS_HANDLER_RESULT (result);
        }
 
        /*
-        * Issue final callback if the invoke_type is POST_BODY and the error
+        * Issue final callback if the invoke_type is FINISHED and the error
         * class is not INFORMATIONAL. 
         */
-       if (invoke_type == SOUP_HANDLER_POST_BODY && 
+       if (invoke_type == SOUP_HANDLER_FINISHED && 
            msg->errorclass != SOUP_ERROR_CLASS_INFORMATIONAL) {
                soup_message_issue_callback (msg);
                return TRUE;
@@ -823,146 +804,209 @@ soup_message_run_handlers (SoupMessage *msg, SoupHandlerType invoke_type)
        return FALSE;
 }
 
-static void 
-add_handler (SoupMessage      *msg,
-            SoupHandlerType   type,
-            SoupCallbackFn    handler_cb,
-            gpointer          user_data,
-            SoupHandlerKind   kind,
-            const gchar      *header,
-            guint             errorcode,
-            guint             errorclass)
+static gboolean
+timeout_handler (gpointer user_data)
 {
-       SoupHandlerData *data;
+       SoupHandlerData *data = user_data;
+       SoupMessage *msg = data->msg;
+       SoupHandlerResult result;
+       GSList *iter;
+
+       switch (data->type) {
+       case SOUP_HANDLER_PREPARE:
+               if (msg->status >= SOUP_STATUS_SENDING_REQUEST)
+                       goto REMOVE_SOURCE;
+       case SOUP_HANDLER_HEADERS:
+       case SOUP_HANDLER_DATA:
+               if (msg->status >= SOUP_STATUS_READING_RESPONSE &&
+                   g_hash_table_size (msg->response_headers) > 0)
+                       goto REMOVE_SOURCE;
+       case SOUP_HANDLER_FINISHED:
+               if (msg->status == SOUP_STATUS_FINISHED)
+                       goto REMOVE_SOURCE;
+       case SOUP_HANDLER_DATA_SENT:
+               iter = msg->priv->content_handlers; 
+               while (iter) {
+                       SoupHandlerData *hd = iter->data;
+                       if (!g_strcasecmp (hd->name, "server-message"))
+                               goto REMOVE_SOURCE;
+               }
+       }
 
-       data = g_new0 (SoupHandlerData, 1);
-       data->type = type;
-       data->handler_cb = handler_cb;
-       data->user_data = user_data;
-       data->kind = kind;
+       result = (*data->handler_cb) (msg, data->user_data);
 
-       switch (kind) {
-       case RESPONSE_HEADER_HANDLER:
-               data->data.header = header;
+       switch (result) {
+       case SOUP_HANDLER_KILL:
+               soup_message_cancel (msg);
                break;
-       case RESPONSE_ERROR_CODE_HANDLER:
-               data->data.errorcode = errorcode;
-               break;
-       case RESPONSE_ERROR_CLASS_HANDLER:
-               data->data.errorclass = errorclass;
+       case SOUP_HANDLER_RESEND:
+               soup_message_queue (msg,
+                                   msg->priv->callback,
+                                   msg->priv->user_data);
                break;
        default:
                break;
        }
 
-       msg->priv->content_handlers = 
-               g_slist_append (msg->priv->content_handlers, data);
+ REMOVE_SOURCE:
+       data->timeout_tag = 0;
+       return FALSE;
 }
 
 void 
-soup_message_add_header_handler (SoupMessage      *msg,
-                                const gchar      *header,
-                                SoupHandlerType   type,
-                                SoupCallbackFn    handler_cb,
-                                gpointer          user_data)
+soup_message_add_handler_full (SoupMessage       *msg,
+                              const gchar       *name,
+                              SoupHandlerEvent   type,
+                              SoupHandlerWhen    order,
+                              SoupHandlerFilter *filter,
+                              SoupHandlerFn      handler_cb,
+                              gpointer           user_data)
 {
+       SoupHandlerData *data;
+
        g_return_if_fail (msg != NULL);
-       g_return_if_fail (header != NULL);
+       g_return_if_fail (type != 0);
+       g_return_if_fail (order != 0);
        g_return_if_fail (handler_cb != NULL);
 
-       add_handler (msg, 
-                    type, 
-                    handler_cb, 
-                    user_data, 
-                    RESPONSE_HEADER_HANDLER, 
-                    header, 
-                    0,
-                    0);
+       data = g_new0 (SoupHandlerData, 1);
+       data->type = type;
+       data->handler_cb = handler_cb;
+       data->user_data = user_data;
+       data->name = g_strdup (name);
+       data->order = order;
+       data->msg = msg;
+
+       if (filter) {
+               data->filter.type = filter->type;
+       
+               switch (filter->type) {
+               case SOUP_FILTER_HEADER:
+                       data->filter.data.header = 
+                               g_strdup (filter->data.header);
+                       break;
+               case SOUP_FILTER_ERROR_CODE:
+                       data->filter.data.errorcode = filter->data.errorcode;
+                       break;
+               case SOUP_FILTER_ERROR_CLASS:
+                       data->filter.data.errorclass = filter->data.errorclass;
+                       break;
+               case SOUP_FILTER_TIMEOUT:
+                       data->filter.data.timeout = filter->data.timeout;
+                       data->timeout_tag = 
+                               g_timeout_add (filter->data.timeout * 1000,
+                                              timeout_handler,
+                                              data);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       msg->priv->content_handlers = 
+               g_slist_append (msg->priv->content_handlers, data);
 }
 
 void 
-soup_message_add_error_code_handler (SoupMessage      *msg,
-                                    guint             errorcode,
-                                    SoupHandlerType   type,
-                                    SoupCallbackFn    handler_cb,
-                                    gpointer          user_data)
+soup_message_add_handler (SoupMessage       *msg,
+                         SoupHandlerEvent   type,
+                         SoupHandlerFilter *filter,
+                         SoupHandlerFn      handler_cb,
+                         gpointer           user_data)
 {
        g_return_if_fail (msg != NULL);
-       g_return_if_fail (errorcode != 0);
+       g_return_if_fail (type != 0);
        g_return_if_fail (handler_cb != NULL);
 
-       add_handler (msg, 
-                    type, 
-                    handler_cb, 
-                    user_data, 
-                    RESPONSE_ERROR_CODE_HANDLER, 
-                    NULL, 
-                    errorcode,
-                    0);
+       soup_message_add_handler_full (msg,
+                                      NULL,
+                                      type,
+                                      SOUP_HANDLER_LAST,
+                                      filter,
+                                      handler_cb,
+                                      user_data);
+}
+
+GSList *
+soup_message_list_handlers (SoupMessage *msg)
+{
+       GSList *ret = NULL, *list;
+
+       g_return_val_if_fail (msg != NULL, NULL);
+
+       for (list = msg->priv->content_handlers; list; list = list->next) {
+               SoupHandlerData *data = list->data;
+               if (data->name)
+                       ret = g_slist_append (ret, data->name);
+       }
+
+       return ret;
 }
 
 void 
-soup_message_add_error_class_handler (SoupMessage      *msg,
-                                     SoupErrorClass    errorclass,
-                                     SoupHandlerType   type,
-                                     SoupCallbackFn    handler_cb,
-                                     gpointer          user_data)
+soup_message_remove_handler (SoupMessage       *msg, 
+                            gchar             *name)
 {
+       GSList *iter;
+
        g_return_if_fail (msg != NULL);
-       g_return_if_fail (errorclass != 0);
-       g_return_if_fail (handler_cb != NULL);
+       g_return_if_fail (name != NULL);
+
+       iter = msg->priv->content_handlers;
+       while (iter) {
+               SoupHandlerData *data = iter->data;
+
+               if (data->name && !g_strcasecmp (data->name, name)) {
+                       handler_free (data);
+                       break;
+               }
 
-       add_handler (msg, 
-                    type, 
-                    handler_cb, 
-                    user_data, 
-                    RESPONSE_ERROR_CLASS_HANDLER, 
-                    NULL, 
-                    0,
-                    errorclass);
+               iter = iter->next;
+       }
 }
 
 void 
-soup_message_add_handler (SoupMessage      *msg,
-                         SoupHandlerType   type,
-                         SoupCallbackFn    handler_cb,
-                         gpointer          user_data)
+soup_message_remove_handler_by_func (SoupMessage       *msg, 
+                                    SoupHandlerFn      handler_cb)
 {
+       GSList *iter;
+
        g_return_if_fail (msg != NULL);
        g_return_if_fail (handler_cb != NULL);
 
-       add_handler (msg, 
-                    type, 
-                    handler_cb, 
-                    user_data, 
-                    0, 
-                    NULL, 
-                    0,
-                    0);
+       iter = msg->priv->content_handlers;
+       while (iter) {
+               SoupHandlerData *data = iter->data;
+
+               if (data->handler_cb == handler_cb) {
+                       handler_free (data);
+                       break;
+               }
+
+               iter = iter->next;
+       }
 }
 
-void
-soup_message_remove_handler (SoupMessage     *msg, 
-                            SoupHandlerType  type,
-                            SoupCallbackFn   handler_cb,
-                            gpointer         user_data)
+void 
+soup_message_remove_handler_by_func_and_data (SoupMessage       *msg, 
+                                             SoupHandlerFn      handler_cb,
+                                             gpointer           user_data)
 {
-       GSList *iter = msg->priv->content_handlers;
+       GSList *iter;
 
+       g_return_if_fail (msg != NULL);
+       g_return_if_fail (handler_cb != NULL);
+
+       iter = msg->priv->content_handlers;
        while (iter) {
                SoupHandlerData *data = iter->data;
 
-               if (data->handler_cb == handler_cb &&
-                   data->user_data == user_data &&
-                   data->type == type) {
-                       msg->priv->content_handlers = 
-                               g_slist_remove_link (
-                                       msg->priv->content_handlers,
-                                       iter);
-                       g_free (data);
+               if (data->handler_cb == handler_cb && 
+                   data->user_data == user_data) {
+                       handler_free (data);
                        break;
                }
-               
+
                iter = iter->next;
        }
 }
index 6ddfa05..7a8b613 100644 (file)
@@ -181,39 +181,111 @@ guint          soup_message_get_flags           (SoupMessage        *msg);
  * Handler Registration 
  */
 typedef enum {
-       SOUP_HANDLER_PRE_BODY = 1,
-       SOUP_HANDLER_BODY_CHUNK,
-       SOUP_HANDLER_POST_BODY
-} SoupHandlerType;
+       /*
+        * Client-side events
+        */
+       SOUP_HANDLER_PREPARE = 0,
+       SOUP_HANDLER_HEADERS,
+       SOUP_HANDLER_DATA,
+       SOUP_HANDLER_FINISHED,
+
+       /*
+        * Server-side events
+        */
+       SOUP_HANDLER_DATA_SENT
+} SoupHandlerEvent;
+
+enum {
+       SOUP_FILTER_HEADER      = (1 << 0),
+       SOUP_FILTER_ERROR_CODE  = (1 << 1),
+       SOUP_FILTER_ERROR_CLASS = (1 << 2),
+       SOUP_FILTER_TIMEOUT     = (1 << 3),
+} SoupHandlerFilterType;
+
+typedef struct {
+       gint type;
+
+       union {
+               guint               errorcode;
+               SoupErrorClass      errorclass;
+               const gchar        *header;
+               guint               timeout;
+       } data;
+} SoupHandlerFilter;
+
+typedef enum {
+       /*
+        * Continue processing as normal.
+        */
+       SOUP_HANDLER_CONTINUE,
+
+       /*
+        * Do not process further handlers.  Continue receiving data.
+        */
+       SOUP_HANDLER_STOP,
+
+       /*
+        * do not process further handlers.  Stop receiving data and 
+        * issue final callback.
+        */
+       SOUP_HANDLER_KILL,
+
+       /*
+        * Restart handler processing.  This should be returned if a 
+        * handler changes the message's errorcode.
+        */
+       SOUP_HANDLER_RESTART,
+
+       /*
+        * Requeue the request immediately.  Stop processing handlers 
+        * and do not issue final callback.
+        */
+       SOUP_HANDLER_RESEND
+} SoupHandlerResult;
+
+typedef SoupHandlerResult (*SoupHandlerFn) (SoupMessage *req, 
+                                           gpointer     user_data);
 
 void           soup_message_add_handler         (SoupMessage       *msg,
-                                                SoupHandlerType    type,
-                                                SoupCallbackFn     handler_cb,
+                                                SoupHandlerEvent   type,
+                                                SoupHandlerFilter *filter,
+                                                SoupHandlerFn      handler_cb,
                                                 gpointer           user_data);
 
-void           soup_message_add_header_handler  (SoupMessage       *msg,
-                                                const gchar       *header,
-                                                SoupHandlerType    type,
-                                                SoupCallbackFn     handler_cb,
-                                                gpointer           user_data);
+typedef enum {
+       /*
+        * Run before global handlers and previously registered message
+        * handlers. 
+        */
+       SOUP_HANDLER_FIRST,
 
-void           soup_message_add_error_code_handler (
-                                                SoupMessage       *msg,
-                                                guint              errorcode,
-                                                SoupHandlerType    type,
-                                                SoupCallbackFn     handler_cb,
-                                                gpointer           user_data);
+       /*
+        * Run after global handlers and previously registered message
+        * handlers. 
+        */
+       SOUP_HANDLER_LAST
+} SoupHandlerWhen;
 
-void           soup_message_add_error_class_handler (
-                                                SoupMessage       *msg,
-                                                SoupErrorClass     errorclass,
-                                                SoupHandlerType    type,
-                                                SoupCallbackFn     handler_cb,
+void           soup_message_add_handler_full    (SoupMessage       *msg,
+                                                const gchar       *name,
+                                                SoupHandlerEvent   type,
+                                                SoupHandlerWhen    order,
+                                                SoupHandlerFilter *filter,
+                                                SoupHandlerFn      handler_cb,
                                                 gpointer           user_data);
 
+GSList        *soup_message_list_handlers       (SoupMessage       *msg);
+
 void           soup_message_remove_handler      (SoupMessage       *msg, 
-                                                SoupHandlerType    type,
-                                                SoupCallbackFn     handler_cb,
+                                                gchar             *name);
+
+void           soup_message_remove_handler_by_func (
+                                                SoupMessage       *msg, 
+                                                SoupHandlerFn      handler_cb);
+
+void           soup_message_remove_handler_by_func_and_data (
+                                                SoupMessage       *msg, 
+                                                SoupHandlerFn      handler_cb,
                                                 gpointer           user_data);
 
 /*
@@ -230,24 +302,4 @@ void           soup_message_set_handler_error   (SoupMessage       *msg,
                                                 guint              errcode, 
                                                 const gchar       *errphrase);
 
-/** DEPRECATED API **/
-
-/** DEPRECATED **/
-void           soup_message_set_request_header  (SoupMessage       *req,
-                                                const gchar       *name,
-                                                const gchar       *value);
-
-/** DEPRECATED **/
-const gchar   *soup_message_get_request_header  (SoupMessage       *req,
-                                                const gchar       *name);
-
-/** DEPRECATED **/
-void           soup_message_set_response_header (SoupMessage       *req,
-                                                const gchar       *name,
-                                                const gchar       *value);
-
-/** DEPRECATED **/
-const gchar   *soup_message_get_response_header (SoupMessage       *req,
-                                                const gchar       *name);
-
 #endif /*SOUP_MESSAGE_H*/
index 416d440..5fc92a1 100644 (file)
@@ -150,7 +150,7 @@ struct _SoupServer {
 void     soup_message_issue_callback (SoupMessage      *req);
 
 gboolean soup_message_run_handlers   (SoupMessage      *msg,
-                                     SoupHandlerType   invoke_type);
+                                     SoupHandlerEvent  invoke_type);
 
 void     soup_message_cleanup        (SoupMessage      *req);
 
index f3cd309..0faa268 100644 (file)
@@ -184,7 +184,7 @@ soup_queue_read_headers_cb (const GString        *headers,
        }
 
  RUN_HANDLERS:
-       if (soup_message_run_handlers (req, SOUP_HANDLER_PRE_BODY))
+       if (soup_message_run_handlers (req, SOUP_HANDLER_HEADERS))
                return SOUP_TRANSFER_END;
 
        return SOUP_TRANSFER_CONTINUE;
@@ -204,7 +204,7 @@ soup_queue_read_chunk_cb (const SoupDataBuffer *data,
        req->response.length = data->length;
        req->response.body = data->body;
 
-       if (soup_message_run_handlers (req, SOUP_HANDLER_BODY_CHUNK))
+       if (soup_message_run_handlers (req, SOUP_HANDLER_DATA))
                return SOUP_TRANSFER_END;
 
        return SOUP_TRANSFER_CONTINUE;
@@ -243,7 +243,7 @@ soup_queue_read_done_cb (const SoupDataBuffer *data,
                req->priv->read_tag = 0;
        }
 
-       soup_message_run_handlers (req, SOUP_HANDLER_POST_BODY);
+       soup_message_run_handlers (req, SOUP_HANDLER_FINISHED);
 }
 
 static void
@@ -431,7 +431,7 @@ soup_queue_connect_cb (SoupContext          *ctx,
        req->priv->connect_tag = NULL;
 
        switch (err) {
-       case SOUP_CONNECT_ERROR_NONE:           
+       case SOUP_CONNECT_ERROR_NONE:
                proto = soup_context_get_uri (ctx)->protocol;
 
                if (soup_connection_is_new (conn) &&