diff --git a/include/proto/dumpstats.h b/include/proto/dumpstats.h index 9cf5eec40..e33fe944c 100644 --- a/include/proto/dumpstats.h +++ b/include/proto/dumpstats.h @@ -3,7 +3,7 @@ * This file contains definitions of some primitives to dedicated to * statistics output. * - * Copyright (C) 2000-2010 Willy Tarreau - w@1wt.eu + * Copyright (C) 2000-2011 Willy Tarreau - w@1wt.eu * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -61,6 +61,8 @@ #define STAT_STATUS_EXCD "EXCD" /* an error occured becayse the buffer couldn't store all data */ #define STAT_STATUS_DENY "DENY" /* action denied */ +extern struct si_applet http_stats_applet; +extern struct si_applet cli_applet; int stats_accept(struct session *s); int stats_sock_parse_request(struct stream_interface *si, char *line); @@ -71,7 +73,6 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri); int stats_dump_sess_to_buffer(struct session *s, struct buffer *rep); int stats_dump_table_to_buffer(struct session *s, struct buffer *rep); int stats_dump_errors_to_buffer(struct session *s, struct buffer *rep); -void http_stats_io_handler(struct stream_interface *si); #endif /* _PROTO_DUMPSTATS_H */ diff --git a/include/proto/stream_interface.h b/include/proto/stream_interface.h index 4e7f73419..0b90fcba2 100644 --- a/include/proto/stream_interface.h +++ b/include/proto/stream_interface.h @@ -2,7 +2,7 @@ * include/proto/stream_interface.h * This file contains stream_interface function prototypes * - * Copyright (C) 2000-2009 Willy Tarreau - w@1wt.eu + * Copyright (C) 2000-2011 Willy Tarreau - w@1wt.eu * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -42,7 +42,7 @@ void stream_int_chk_rcv(struct stream_interface *si); void stream_int_chk_snd(struct stream_interface *si); struct task *stream_int_register_handler(struct stream_interface *si, - void (*fct)(struct stream_interface *)); + struct si_applet *app); struct task *stream_int_register_handler_task(struct stream_interface *si, struct task *(*fct)(struct task *)); void stream_int_unregister_handler(struct stream_interface *si); diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h index cfba68735..6af0f63d6 100644 --- a/include/types/stream_interface.h +++ b/include/types/stream_interface.h @@ -2,7 +2,7 @@ * include/types/stream_interface.h * This file describes the stream_interface struct and associated constants. * - * Copyright (C) 2000-2010 Willy Tarreau - w@1wt.eu + * Copyright (C) 2000-2011 Willy Tarreau - w@1wt.eu * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -78,13 +78,11 @@ enum { struct server; struct proxy; +struct si_applet; -/* Note that if an iohandler is set, the update function will not be called by - * the session handler, so it may be used to resync flags at the end of the I/O - * handler. See stream_int_update_embedded() for reference. - * This struct could be optimized, because : - * - connect(), fd, conn_retries are only used in stream_sock mode - * - iohandler(), private, st0, st1 are only used in iohandler mode +/* Note that if an applet is registered, the update function will not be called + * by the session handler, so it may be used to resync flags at the end of the + * applet handler. See stream_int_update_embedded() for reference. */ struct stream_interface { unsigned int state; /* SI_ST* */ @@ -101,15 +99,22 @@ struct stream_interface { int (*connect)(struct stream_interface *, struct proxy *, struct server *, struct sockaddr *, struct sockaddr *); /* connect function if any */ void (*release)(struct stream_interface *); /* handler to call after the last close() */ - void (*iohandler)(struct stream_interface *); /* internal I/O handler when embedded */ struct buffer *ib, *ob; /* input and output buffers */ int conn_retries; /* number of connect retries left */ unsigned int err_type; /* first error detected, one of SI_ET_* */ void *err_loc; /* commonly the server, NULL when SI_ET_NONE */ + struct { + struct si_applet *handler; /* applet to use instead of doing I/O */ + } applet; void *private; /* may be used by any function above */ unsigned int st0, st1; /* may be used by any function above */ }; +/* An applet designed to run in a stream interface */ +struct si_applet { + char *name; /* applet's name to report in logs */ + void (*fct)(struct stream_interface *); /* internal I/O handler, may never be NULL */ +}; #endif /* _TYPES_STREAM_INTERFACE_H */ diff --git a/src/dumpstats.c b/src/dumpstats.c index 081e4cd37..2630eed9a 100644 --- a/src/dumpstats.c +++ b/src/dumpstats.c @@ -84,7 +84,7 @@ const char stats_permission_denied_msg[] = int stats_accept(struct session *s) { /* we have a dedicated I/O handler for the stats */ - stream_int_register_handler(&s->si[1], stats_io_handler); + stream_int_register_handler(&s->si[1], &cli_applet); s->si[1].private = s; s->si[1].st1 = 0; s->si[1].st0 = STAT_CLI_INIT; @@ -848,7 +848,7 @@ int stats_sock_parse_request(struct stream_interface *si, char *line) * STAT_CLI_* constants. si->st1 is used to indicate whether prompt is enabled * or not. */ -void stats_io_handler(struct stream_interface *si) +static void cli_io_handler(struct stream_interface *si) { struct session *s = si->private; struct buffer *req = si->ob; @@ -1200,7 +1200,7 @@ int stats_http_redir(struct session *s, struct buffer *rep, struct uri_auth *uri * si->st0 becomes non-zero once the transfer is finished. The handler * automatically unregisters itself once transfer is complete. */ -void http_stats_io_handler(struct stream_interface *si) +static void http_stats_io_handler(struct stream_interface *si) { struct session *s = si->private; struct buffer *req = si->ob; @@ -3583,6 +3583,15 @@ int stats_dump_errors_to_buffer(struct session *s, struct buffer *rep) return 1; } +struct si_applet http_stats_applet = { + .name = "", /* used for logging */ + .fct = http_stats_io_handler, +}; + +struct si_applet cli_applet = { + .name = "", /* used for logging */ + .fct = cli_io_handler, +}; static struct cfg_kw_list cfg_kws = {{ },{ { CFG_GLOBAL, "stats", stats_parse_global }, diff --git a/src/peers.c b/src/peers.c index 19b882412..39f4a359b 100644 --- a/src/peers.c +++ b/src/peers.c @@ -216,7 +216,7 @@ void peer_session_release(struct stream_interface *si) /* * IO Handler to handle message exchance with a peer */ -void peer_io_handler(struct stream_interface *si) +static void peer_io_handler(struct stream_interface *si) { struct task *t= (struct task *)si->owner; struct session *s = (struct session *)t->context; @@ -1041,6 +1041,10 @@ quit: return; } +static struct si_applet peer_applet = { + .name = "", /* used for logging */ + .fct = peer_io_handler, +}; /* * Use this function to force a close of a peer session @@ -1049,7 +1053,7 @@ void peer_session_forceshutdown(struct session * session) { struct stream_interface *oldsi; - if (session->si[0].iohandler == peer_io_handler) { + if (session->si[0].applet.handler == &peer_applet) { oldsi = &session->si[0]; } else { @@ -1072,7 +1076,7 @@ void peer_session_forceshutdown(struct session * session) int peer_accept(struct session *s) { /* we have a dedicated I/O handler for the stats */ - stream_int_register_handler(&s->si[1], peer_io_handler); + stream_int_register_handler(&s->si[1], &peer_applet); s->si[1].release = peer_session_release; s->si[1].private = s; s->si[1].st0 = PEER_SESSION_ACCEPT; @@ -1158,7 +1162,7 @@ struct session *peer_session_create(struct peer *peer, struct peer_session *ps) s->si[0].private = (void *)ps; s->si[0].st0 = PEER_SESSION_CONNECT; - stream_int_register_handler(&s->si[0], peer_io_handler); + stream_int_register_handler(&s->si[0], &peer_applet); s->si[0].release = peer_session_release; s->si[1].fd = -1; /* just to help with debugging */ diff --git a/src/proto_http.c b/src/proto_http.c index 649f5df6a..5119d3725 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -3226,7 +3226,7 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s s->data_source = DATA_SRC_STATS; s->data_state = DATA_ST_INIT; s->task->nice = -32; /* small boost for HTTP statistics */ - stream_int_register_handler(s->rep->prod, http_stats_io_handler); + stream_int_register_handler(s->rep->prod, &http_stats_applet); s->rep->prod->private = s; s->rep->prod->st0 = s->rep->prod->st1 = 0; req->analysers = 0; diff --git a/src/session.c b/src/session.c index 120f670f7..7bcdb5dcc 100644 --- a/src/session.c +++ b/src/session.c @@ -167,7 +167,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) s->si[0].err_type = SI_ET_NONE; s->si[0].err_loc = NULL; s->si[0].connect = NULL; - s->si[0].iohandler = NULL; + s->si[0].applet.handler = NULL; s->si[0].release = NULL; s->si[0].exp = TICK_ETERNITY; s->si[0].flags = SI_FL_NONE; @@ -190,7 +190,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) s->si[1].err_type = SI_ET_NONE; s->si[1].err_loc = NULL; s->si[1].connect = NULL; - s->si[1].iohandler = NULL; + s->si[1].applet.handler = NULL; s->si[1].release = NULL; s->si[1].shutr = stream_int_shutr; s->si[1].shutw = stream_int_shutw; @@ -1786,13 +1786,13 @@ struct task *process_session(struct task *t) if (s->req->cons->state == SI_ST_INI) { if (!(s->req->flags & BF_SHUTW)) { if ((s->req->flags & (BF_AUTO_CONNECT|BF_OUT_EMPTY)) != BF_OUT_EMPTY) { - /* If we have an iohandler without a connect method, we immediately + /* If we have an applet without a connect method, we immediately * switch to the connected state, otherwise we perform a connection * request. */ s->req->cons->state = SI_ST_REQ; /* new connection requested */ s->req->cons->conn_retries = s->be->conn_retries; - if (unlikely(s->req->cons->iohandler && !s->req->cons->connect)) { + if (unlikely(s->req->cons->applet.handler && !s->req->cons->connect)) { s->req->cons->state = SI_ST_EST; /* connection established */ s->rep->flags |= BF_READ_ATTACHED; /* producer is now attached */ s->req->wex = TICK_ETERNITY; @@ -1949,10 +1949,10 @@ struct task *process_session(struct task *t) if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED)) session_process_counters(s); - if (s->rep->cons->state == SI_ST_EST && !s->rep->cons->iohandler) + if (s->rep->cons->state == SI_ST_EST && !s->rep->cons->applet.handler) s->rep->cons->update(s->rep->cons); - if (s->req->cons->state == SI_ST_EST && !s->req->cons->iohandler) + if (s->req->cons->state == SI_ST_EST && !s->req->cons->applet.handler) s->req->cons->update(s->req->cons); s->req->flags &= ~(BF_READ_NULL|BF_READ_PARTIAL|BF_WRITE_NULL|BF_WRITE_PARTIAL|BF_READ_ATTACHED); @@ -1979,11 +1979,11 @@ struct task *process_session(struct task *t) /* Call the stream interfaces' I/O handlers when embedded. * Note that this one may wake the task up again. */ - if (s->req->cons->iohandler || s->rep->cons->iohandler) { - if (s->req->cons->iohandler) - s->req->cons->iohandler(s->req->cons); - if (s->rep->cons->iohandler) - s->rep->cons->iohandler(s->rep->cons); + if (s->req->cons->applet.handler || s->rep->cons->applet.handler) { + if (s->req->cons->applet.handler) + s->req->cons->applet.handler->fct(s->req->cons); + if (s->rep->cons->applet.handler) + s->rep->cons->applet.handler->fct(s->rep->cons); if (task_in_rq(t)) { /* If we woke up, we don't want to requeue the * task to the wait queue, but rather requeue diff --git a/src/stream_interface.c b/src/stream_interface.c index e93048e8d..71fc864a0 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -1,7 +1,7 @@ /* * Functions managing stream_interface structures * - * Copyright 2000-2009 Willy Tarreau + * Copyright 2000-2011 Willy Tarreau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -297,14 +297,13 @@ void stream_int_chk_snd(struct stream_interface *si) task_wakeup(si->owner, TASK_WOKEN_IO); } -/* Register a function to handle a stream_interface as part of the stream +/* Register an applet to handle a stream_interface as part of the stream * interface's owner task, which is returned. The SI will wake it up everytime - * it is solicited. The task's processing function must call the specified + * it is solicited. The task's processing function must call the applet's * function before returning. It must be deleted by the task handler using - * stream_int_unregister_handler(), possibly from withing the function itself. + * stream_int_unregister_handler(), possibly from within the function itself. */ -struct task *stream_int_register_handler(struct stream_interface *si, - void (*fct)(struct stream_interface *)) +struct task *stream_int_register_handler(struct stream_interface *si, struct si_applet *app) { DPRINTF(stderr, "registering handler %p for si %p (was %p)\n", fct, si, si->owner); @@ -314,7 +313,7 @@ struct task *stream_int_register_handler(struct stream_interface *si, si->chk_rcv = stream_int_chk_rcv; si->chk_snd = stream_int_chk_snd; si->connect = NULL; - si->iohandler = fct; + si->applet.handler = app; si->release = NULL; si->flags |= SI_FL_WAIT_DATA; return si->owner; @@ -338,7 +337,7 @@ struct task *stream_int_register_handler_task(struct stream_interface *si, si->chk_rcv = stream_int_chk_rcv; si->chk_snd = stream_int_chk_snd; si->connect = NULL; - si->iohandler = NULL; /* not used when running as an external task */ + si->applet.handler = NULL; /* not used when running as an external task */ si->release = NULL; si->flags |= SI_FL_WAIT_DATA; @@ -359,12 +358,12 @@ struct task *stream_int_register_handler_task(struct stream_interface *si, */ void stream_int_unregister_handler(struct stream_interface *si) { - if (!si->iohandler && si->owner) { + if (!si->applet.handler && si->owner) { /* external handler : kill the task */ task_delete(si->owner); task_free(si->owner); } - si->iohandler = NULL; + si->applet.handler = NULL; si->release = NULL; si->owner = NULL; } diff --git a/src/stream_sock.c b/src/stream_sock.c index 25573cb6f..3c8563e26 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -1252,7 +1252,7 @@ void stream_sock_prepare_interface(struct stream_interface *si) si->shutw = stream_sock_shutw; si->chk_rcv = stream_sock_chk_rcv; si->chk_snd = stream_sock_chk_snd; - si->iohandler = NULL; + si->applet.handler = NULL; }