]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] reference the current hijack function in the buffer itself
authorWilly Tarreau <w@1wt.eu>
Sun, 7 Dec 2008 17:03:29 +0000 (18:03 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 7 Dec 2008 17:03:29 +0000 (18:03 +0100)
Instead of calling a hard-coded function to produce data, let's
reference this function into the buffer and call it from there
when BF_HIJACK is set. This goes in the direction of more generic
session management code.

include/proto/buffers.h
include/proto/dumpstats.h
include/proto/proto_http.h
include/types/buffers.h
src/dumpstats.c
src/proto_http.c
src/proto_uxst.c
src/session.c

index 536f5a11b2de64a3aabaa4f1379d6ba928f74f2c..bc472a069acecd497d58e0402eec56346b60c723 100644 (file)
@@ -126,13 +126,21 @@ static inline void buffer_abort(struct buffer *buf)
        buf->flags |= BF_SHUTR_NOW | BF_SHUTW_NOW;
 }
 
-/* set the buffer to hijacking mode */
-static inline void buffer_start_hijack(struct buffer *buf)
+/* Installs <func> as a hijacker on the buffer <b> for session <s>. The hijack
+ * flag is set, and the function called once. The function is responsible for
+ * clearing the hijack bit. It is possible that the function clears the flag
+ * during this first call.
+ */
+static inline void buffer_install_hijacker(struct session *s,
+                                          struct buffer *b,
+                                          void (*func)(struct session *, struct buffer *))
 {
-       buf->flags |= BF_HIJACK;
+       b->hijacker = func;
+       b->flags |= BF_HIJACK;
+       func(s, b);
 }
 
-/* releases the buffer from hijacking mode */
+/* Releases the buffer from hijacking mode. Often used by the hijack function */
 static inline void buffer_stop_hijack(struct buffer *buf)
 {
        buf->flags &= ~BF_HIJACK;
index a7c5ab4999f4150676648cfacf1b60d50eab9198..bc6bdad37dabbb573db41eec884938ed65934b25 100644 (file)
@@ -45,7 +45,7 @@
 #define STATS_ST_CLOSE 3
 
 int stats_dump_raw(struct session *s, struct uri_auth *uri);
-int stats_dump_raw_to_buffer(struct session *s, struct buffer *req);
+void stats_dump_raw_to_buffer(struct session *s, struct buffer *req);
 int stats_dump_http(struct session *s, struct uri_auth *uri);
 int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri);
 
index c7236518713b3d2bad9daefc3ec12d1ae1de6449..41f1922a94a6bdb2693713c011f8234254496398 100644 (file)
@@ -66,7 +66,7 @@ int http_process_tarpit(struct session *s, struct buffer *req);
 int http_process_request_body(struct session *s, struct buffer *req);
 int process_response(struct session *t);
 
-int produce_content(struct session *s);
+void produce_content(struct session *s, struct buffer *rep);
 int produce_content_stats(struct session *s);
 int produce_content_stats_proxy(struct session *s, struct proxy *px);
 void debug_hdr(const char *dir, struct session *t, const char *start, const char *end);
index 665c75d79d007d2483d31e4f541d87f0ed5f283d..3c79a4edd7cf8bfa67beea117aca8bf2beae5897 100644 (file)
@@ -80,7 +80,7 @@
  * it is strictly forbidden for the stream interface to send anything from the
  * buffer.
  */
-#define BF_HIJACK         0x040000  /* the producer is temporarily replaced */
+#define BF_HIJACK         0x040000  /* the producer is temporarily replaced by ->hijacker */
 #define BF_ANA_TIMEOUT    0x080000  /* the analyser timeout has expired */
 #define BF_READ_ATTACHED  0x100000  /* the read side is attached for the first time */
 
@@ -116,6 +116,9 @@ struct chunk {
        int len;        /* size of the string from first to last char. <0 = uninit. */
 };
 
+/* needed for a declaration below */
+struct session;
+
 struct buffer {
        unsigned int flags;             /* BF_* */
        int rex;                        /* expiration date for a read, in ticks */
@@ -128,6 +131,7 @@ struct buffer {
        char *rlim;                     /* read limit, used for header rewriting */
        unsigned int analysers;         /* bit field indicating what to do on the buffer */
        int analyse_exp;                /* expiration date for current analysers (if set) */
+       void (*hijacker)(struct session *, struct buffer *); /* alternative content producer */
        unsigned char xfer_large;       /* number of consecutive large xfers */
        unsigned char xfer_small;       /* number of consecutive small xfers */
        unsigned long long total;       /* total data read */
index 215e1490237ed989db07d17b86ff61e48c24429e..590edbe7ee2c0566655e91a3eb741e9cc8723402 100644 (file)
@@ -290,18 +290,18 @@ int stats_dump_raw(struct session *s, struct uri_auth *uri)
 
 /* This function is called to send output to the response buffer. It simply
  * calls stats_dump_raw(), and releases the buffer's hijack bit when the dump
- * is finished. It always returns 0.
+ * is finished.
  */
-int stats_dump_raw_to_buffer(struct session *s, struct buffer *req)
+void stats_dump_raw_to_buffer(struct session *s, struct buffer *req)
 {
        if (s->ana_state != STATS_ST_REP)
-               return 0;
+               return;
 
        if (stats_dump_raw(s, NULL) != 0) {
                buffer_stop_hijack(s->rep);
                s->ana_state = STATS_ST_CLOSE;
        }
-       return 0;
+       return;
 }
 
 
@@ -327,9 +327,6 @@ int stats_dump_http(struct session *s, struct uri_auth *uri)
 
        switch (s->data_state) {
        case DATA_ST_INIT:
-               /* the function had not been called yet */
-               buffer_start_hijack(rep);
-
                chunk_printf(&msg, sizeof(trash),
                             "HTTP/1.0 200 OK\r\n"
                             "Cache-Control: no-cache\r\n"
index e24b01baa7c292acc8cd844f3e56c81aea27e742..092c730abc75c8c0b704304b9e7e702dde7c2c67 100644 (file)
@@ -2989,33 +2989,32 @@ int process_response(struct session *t)
  * called with client socket shut down on input. Right now, only statistics can
  * be produced. It stops by itself by unsetting the BF_HIJACK flag from the
  * buffer, which it uses to keep on being called when there is free space in
- * the buffer, or simply by letting an empty buffer upon return. It returns 1
- * when it wants to stop sending data, otherwise 0.
+ * the buffer, or simply by letting an empty buffer upon return.
  */
-int produce_content(struct session *s)
+void produce_content(struct session *s, struct buffer *rep)
 {
        if (s->data_source == DATA_SRC_NONE) {
-               buffer_stop_hijack(s->rep);
-               return 1;
+               buffer_stop_hijack(rep);
+               return;
        }
        else if (s->data_source == DATA_SRC_STATS) {
                /* dump server statistics */
                int ret = stats_dump_http(s, s->be->uri_auth);
                if (ret >= 0)
-                       return ret;
+                       return;
                /* -1 indicates an error */
        }
 
        /* unknown data source or internal error */
        s->txn.status = 500;
-       stream_int_retnclose(s->rep->cons, error_message(s, HTTP_ERR_500));
+       stream_int_retnclose(rep->cons, error_message(s, HTTP_ERR_500));
        trace_term(s, TT_HTTP_CNT_1);
        if (!(s->flags & SN_ERR_MASK))
                s->flags |= SN_ERR_PRXCOND;
        if (!(s->flags & SN_FINST_MASK))
                s->flags |= SN_FINST_R;
-       buffer_stop_hijack(s->rep);
-       return 1;
+       buffer_stop_hijack(rep);
+       return;
 }
 
 
@@ -4392,12 +4391,11 @@ int stats_check_uri_auth(struct session *t, struct proxy *backend)
        buffer_write_dis(t->req);
        buffer_shutw_now(t->req);
        buffer_shutr_now(t->rep);
-       buffer_start_hijack(t->rep);
        t->logs.tv_request = now;
        t->data_source = DATA_SRC_STATS;
        t->data_state  = DATA_ST_INIT;
        t->task->nice = -32; /* small boost for HTTP statistics */
-       produce_content(t);
+       buffer_install_hijacker(t, t->rep, produce_content);
        return 1;
 }
 
index d7567509e00d06535104d8896e9920854bad4df9..06ec185704ec6fd044589223bdfa6587f3bf0be7 100644 (file)
@@ -596,15 +596,13 @@ int unix_sock_parse_request(struct session *s, char *line)
                        s->data_ctx.stats.flags |= STAT_SHOW_STAT;
                        s->data_ctx.stats.flags |= STAT_FMT_CSV;
                        s->ana_state = STATS_ST_REP;
-                       buffer_start_hijack(s->rep);
-                       stats_dump_raw_to_buffer(s, s->rep);
+                       buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
                }
                else if (strcmp(args[1], "info") == 0) {
                        s->data_ctx.stats.flags |= STAT_SHOW_INFO;
                        s->data_ctx.stats.flags |= STAT_FMT_CSV;
                        s->ana_state = STATS_ST_REP;
-                       buffer_start_hijack(s->rep);
-                       stats_dump_raw_to_buffer(s, s->rep);
+                       buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
                }
                else { /* neither "stat" nor "info" */
                        return 0;
@@ -837,8 +835,7 @@ void uxst_process_session(struct task *t, int *next)
 
                if ((s->rep->flags & (BF_WRITE_PARTIAL|BF_WRITE_ERROR|BF_SHUTW)) &&
                    !(s->rep->flags & BF_FULL)) {
-                       /* it is the only hijacker right now */
-                       stats_dump_raw_to_buffer(s, s->rep);
+                       s->rep->hijacker(s, s->rep);
                }
                s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
                flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
index e19bb56300daab4522229d2e246d99ea6865ba24..a6190730d081701172688a15ebbba79f4df6c5b2 100644 (file)
@@ -805,7 +805,7 @@ resync_stream_interface:
 
                if ((s->rep->flags & (BF_WRITE_PARTIAL|BF_WRITE_ERROR|BF_SHUTW)) &&
                    !(s->rep->flags & BF_FULL)) {
-                       produce_content(s);
+                       s->rep->hijacker(s, s->rep);
                }
                s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;
                flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT;