dougm 01/07/15 15:33:50 Modified: src/modules/perl mod_perl.c modperl_filter.c modperl_filter.h modperl_types.h t/filter/TestFilter input_body.pm input_msg.pm xs/Apache/Filter Apache__Filter.h Log: support connection-level output filters (filter handler attribute names/semantics are still not final) Revision Changes Path 1.60 +9 -4 modperl-2.0/src/modules/perl/mod_perl.c Index: mod_perl.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/mod_perl.c,v retrieving revision 1.59 retrieving revision 1.60 diff -u -r1.59 -r1.60 --- mod_perl.c 2001/07/13 16:49:35 1.59 +++ mod_perl.c 2001/07/15 22:33:48 1.60 @@ -264,7 +264,9 @@ static int modperl_hook_pre_connection(conn_rec *c) { - return modperl_input_filter_register_connection(c); + modperl_input_filter_register_connection(c); + modperl_output_filter_register_connection(c); + return OK; } static void modperl_hook_post_config(apr_pool_t *pconf, apr_pool_t *plog, @@ -297,7 +299,7 @@ /* if 'PerlOptions +GlobalRequest' is outside a container */ modperl_global_request_cfg_set(r); - return modperl_input_filter_register_request(r); + return OK; } static int modperl_hook_header_parser(request_rec *r) @@ -305,7 +307,7 @@ /* if 'PerlOptions +GlobalRequest' is inside a container */ modperl_global_request_cfg_set(r); - return modperl_input_filter_register_request(r); + return OK; } void modperl_register_hooks(apr_pool_t *p) @@ -321,8 +323,11 @@ ap_hook_handler(modperl_response_handler_cgi, NULL, NULL, APR_HOOK_MIDDLE); + + ap_hook_insert_filter(modperl_output_filter_register_request, + NULL, NULL, APR_HOOK_LAST); - ap_hook_insert_filter(modperl_output_filter_register, + ap_hook_insert_filter(modperl_input_filter_register_request, NULL, NULL, APR_HOOK_LAST); ap_register_output_filter(MODPERL_OUTPUT_FILTER_NAME, 1.21 +92 -49 modperl-2.0/src/modules/perl/modperl_filter.c Index: modperl_filter.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_filter.c,v retrieving revision 1.20 retrieving revision 1.21 diff -u -r1.20 -r1.21 --- modperl_filter.c 2001/05/08 21:08:27 1.20 +++ modperl_filter.c 2001/07/15 22:33:48 1.21 @@ -75,12 +75,13 @@ /* generic filter routines */ +#define MP_FILTER_POOL(f) f->r ? f->r->pool : f->c->pool + modperl_filter_t *modperl_filter_new(ap_filter_t *f, apr_bucket_brigade *bb, modperl_filter_mode_e mode) { - apr_pool_t *p = mode == MP_INPUT_FILTER_MODE ? - f->c->pool : f->r->pool; + apr_pool_t *p = MP_FILTER_POOL(f); modperl_filter_t *filter = apr_pcalloc(p, sizeof(*filter)); filter->mode = mode; @@ -152,12 +153,20 @@ MP_INLINE static apr_status_t send_eos(ap_filter_t *f) { - apr_bucket_brigade *bb = apr_brigade_create(f->r->pool); + apr_bucket_brigade *bb = apr_brigade_create(MP_FILTER_POOL(f)); apr_bucket *b = apr_bucket_eos_create(); APR_BRIGADE_INSERT_TAIL(bb, b); return ap_pass_brigade(f->next, bb); } +MP_INLINE static apr_status_t send_flush(ap_filter_t *f) +{ + apr_bucket_brigade *bb = apr_brigade_create(MP_FILTER_POOL(f)); + apr_bucket *b = apr_bucket_flush_create(); + APR_BRIGADE_INSERT_TAIL(bb, b); + return ap_pass_brigade(f->next, bb); +} + /* unrolled APR_BRIGADE_FOREACH loop */ #define MP_FILTER_SENTINEL(filter) \ @@ -172,6 +181,9 @@ #define MP_FILTER_IS_EOS(filter) \ APR_BUCKET_IS_EOS(filter->bucket) +#define MP_FILTER_IS_FLUSH(filter) \ +APR_BUCKET_IS_FLUSH(filter->bucket) + MP_INLINE static int get_bucket(modperl_filter_t *filter) { if (!filter->bb) { @@ -253,6 +265,11 @@ filter->eos = 1; break; } + else if (MP_FILTER_IS_FLUSH(filter)) { + MP_TRACE_f(MP_FUNC, "received FLUSH bucket\n"); + filter->flush = 1; + break; + } num_buckets++; @@ -298,7 +315,7 @@ } #endif - if (filter->eos && (len == 0)) { + if ((filter->eos || filter->flush) && (len == 0)) { /* if len > 0 then $filter->write will flush */ modperl_output_filter_flush(filter); } @@ -313,12 +330,14 @@ return filter->rc; } - if (filter->eos) { - MP_TRACE_f(MP_FUNC, "sending EOS bucket\n"); - filter->rc = send_eos(filter->f); + if (filter->eos || filter->flush) { + MP_TRACE_f(MP_FUNC, "sending %s bucket\n", + filter->eos ? "EOS" : "FLUSH"); + filter->rc = filter->eos ? + send_eos(filter->f) : send_flush(filter->f); apr_brigade_destroy(filter->bb); filter->bb = NULL; - filter->eos = 0; + filter->flush = filter->eos = 0; } return filter->rc; @@ -387,87 +406,74 @@ } } -void modperl_output_filter_register(request_rec *r) -{ - MP_dDCFG; - MpAV *av; +typedef ap_filter_t * (*filter_add_t) (const char *, void *, + request_rec *, conn_rec *); - if ((av = dcfg->handlers_per_dir[MP_OUTPUT_FILTER_HANDLER])) { - modperl_handler_t **handlers = (modperl_handler_t **)av->elts; - int i; - - for (i=0; i<av->nelts; i++) { - modperl_filter_ctx_t *ctx = - (modperl_filter_ctx_t *)apr_pcalloc(r->pool, sizeof(*ctx)); - ctx->handler = handlers[i]; - ap_add_output_filter(MODPERL_OUTPUT_FILTER_NAME, - (void*)ctx, r, r->connection); - } - - return; - } - - MP_TRACE_h(MP_FUNC, "no OutputFilter handlers configured (%s)\n", - r->uri); -} - -int modperl_input_filter_register_connection(conn_rec *c) +static int modperl_filter_register_connection(conn_rec *c, + int idx, + const char *name, + filter_add_t addfunc, + const char *type) { modperl_config_dir_t *dcfg = modperl_config_dir_get_defaults(c->base_server); MpAV *av; - if ((av = dcfg->handlers_per_dir[MP_INPUT_FILTER_HANDLER])) { + if ((av = dcfg->handlers_per_dir[idx])) { modperl_handler_t **handlers = (modperl_handler_t **)av->elts; int i; for (i=0; i<av->nelts; i++) { modperl_filter_ctx_t *ctx; - if (!(handlers[i]->attrs & MP_INPUT_FILTER_MESSAGE)) { + if (!(handlers[i]->attrs & MP_FILTER_CONNECTION_HANDLER)) { MP_TRACE_f(MP_FUNC, - "%s is not an InputFilterMessage handler\n", + "%s is not an FilterConnection handler\n", handlers[i]->name); continue; } ctx = (modperl_filter_ctx_t *)apr_pcalloc(c->pool, sizeof(*ctx)); ctx->handler = handlers[i]; - ap_add_input_filter(MODPERL_INPUT_FILTER_NAME, - (void*)ctx, NULL, c); + addfunc(name, (void*)ctx, NULL, c); } return OK; } - MP_TRACE_h(MP_FUNC, "no InputFilter handlers configured (connection)\n"); + MP_TRACE_h(MP_FUNC, "no %s handlers configured (connection)\n", type); return DECLINED; } -int modperl_input_filter_register_request(request_rec *r) +static int modperl_filter_register_request(request_rec *r, + int idx, + const char *name, + filter_add_t addfunc, + const char *type, + ap_filter_t *filters) { MP_dDCFG; MpAV *av; - if ((av = dcfg->handlers_per_dir[MP_INPUT_FILTER_HANDLER])) { + if ((av = dcfg->handlers_per_dir[idx])) { modperl_handler_t **handlers = (modperl_handler_t **)av->elts; int i; for (i=0; i<av->nelts; i++) { modperl_filter_ctx_t *ctx; int registered = 0; - ap_filter_t *f = r->connection->input_filters; + ap_filter_t *f = filters; while (f) { const char *name = f->frec->name; - if (*name == 'M' && strEQ(name, MODPERL_INPUT_FILTER_NAME)) { + if (*name == 'M' && strEQ(name, name)) { modperl_handler_t *ctx_handler = ((modperl_filter_ctx_t *)f->ctx)->handler; if (modperl_handler_equal(ctx_handler, handlers[i])) { - /* skip if modperl_input_filter_register_connection + /* skip if modperl_filter_register_connection * already registered this handler * XXX: set a flag in the modperl_handler_t instead */ @@ -481,24 +487,61 @@ if (registered) { MP_TRACE_f(MP_FUNC, - "%s InputFilter already registered\n", - handlers[i]->name); + "%s %s already registered\n", + handlers[i]->name, type); continue; } ctx = (modperl_filter_ctx_t *)apr_pcalloc(r->pool, sizeof(*ctx)); ctx->handler = handlers[i]; - ap_add_input_filter(MODPERL_INPUT_FILTER_NAME, - (void*)ctx, r, r->connection); + addfunc(name, (void*)ctx, r, NULL); } return OK; } - MP_TRACE_h(MP_FUNC, "no InputFilter handlers configured (%s)\n", - r->uri); + MP_TRACE_h(MP_FUNC, "no %s handlers configured (%s)\n", + type, r->uri); return DECLINED; +} + +void modperl_output_filter_register_connection(conn_rec *c) +{ + modperl_filter_register_connection(c, + MP_OUTPUT_FILTER_HANDLER, + MODPERL_OUTPUT_FILTER_NAME, + ap_add_output_filter, + "OutputFilter"); +} + +void modperl_output_filter_register_request(request_rec *r) +{ + modperl_filter_register_request(r, + MP_OUTPUT_FILTER_HANDLER, + MODPERL_OUTPUT_FILTER_NAME, + ap_add_output_filter, + "OutputFilter", + r->connection->output_filters); +} + +void modperl_input_filter_register_connection(conn_rec *c) +{ + modperl_filter_register_connection(c, + MP_INPUT_FILTER_HANDLER, + MODPERL_INPUT_FILTER_NAME, + ap_add_input_filter, + "InputFilter"); +} + +void modperl_input_filter_register_request(request_rec *r) +{ + modperl_filter_register_request(r, + MP_INPUT_FILTER_HANDLER, + MODPERL_INPUT_FILTER_NAME, + ap_add_input_filter, + "InputFilter", + r->connection->input_filters); } void modperl_brigade_dump(apr_bucket_brigade *bb, FILE *fp) 1.9 +7 -5 modperl-2.0/src/modules/perl/modperl_filter.h Index: modperl_filter.h =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_filter.h,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- modperl_filter.h 2001/05/07 02:05:01 1.8 +++ modperl_filter.h 2001/07/15 22:33:48 1.9 @@ -4,8 +4,8 @@ #define MODPERL_OUTPUT_FILTER_NAME "MODPERL_OUTPUT" #define MODPERL_INPUT_FILTER_NAME "MODPERL_INPUT" -#define MP_INPUT_FILTER_MESSAGE 0x01 -#define MP_INPUT_FILTER_BODY 0x02 +#define MP_FILTER_CONNECTION_HANDLER 0x01 +#define MP_FILTER_REQUEST_HANDLER 0x02 /* simple buffer api */ MP_INLINE apr_status_t modperl_wbucket_pass(modperl_wbucket_t *b, @@ -32,8 +32,10 @@ apr_status_t modperl_output_filter_handler(ap_filter_t *f, apr_bucket_brigade *bb); -void modperl_output_filter_register(request_rec *r); +void modperl_output_filter_register_connection(conn_rec *c); +void modperl_output_filter_register_request(request_rec *r); + MP_INLINE apr_status_t modperl_output_filter_flush(modperl_filter_t *filter); MP_INLINE apr_ssize_t modperl_output_filter_read(pTHX_ @@ -53,8 +55,8 @@ ap_input_mode_t mode, apr_size_t *readbytes); -int modperl_input_filter_register_connection(conn_rec *c); +void modperl_input_filter_register_connection(conn_rec *c); -int modperl_input_filter_register_request(request_rec *r); +void modperl_input_filter_register_request(request_rec *r); #endif /* MODPERL_FILTER_H */ 1.44 +1 -0 modperl-2.0/src/modules/perl/modperl_types.h Index: modperl_types.h =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_types.h,v retrieving revision 1.43 retrieving revision 1.44 diff -u -r1.43 -r1.44 --- modperl_types.h 2001/05/22 20:57:30 1.43 +++ modperl_types.h 2001/07/15 22:33:48 1.44 @@ -180,6 +180,7 @@ typedef struct { int eos; + int flush; ap_filter_t *f; char *leftover; apr_ssize_t remaining; 1.5 +1 -1 modperl-2.0/t/filter/TestFilter/input_body.pm Index: input_body.pm =================================================================== RCS file: /home/cvs/modperl-2.0/t/filter/TestFilter/input_body.pm,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- input_body.pm 2001/04/24 02:26:17 1.4 +++ input_body.pm 2001/07/15 22:33:49 1.5 @@ -12,7 +12,7 @@ use APR::Brigade (); use APR::Bucket (); -sub handler : InputFilterBody { +sub handler : FilterRequestHandler { my($filter, $bb, $mode, $readbytes) = @_; if ($bb->empty) { 1.6 +1 -1 modperl-2.0/t/filter/TestFilter/input_msg.pm Index: input_msg.pm =================================================================== RCS file: /home/cvs/modperl-2.0/t/filter/TestFilter/input_msg.pm,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- input_msg.pm 2001/04/25 02:02:19 1.5 +++ input_msg.pm 2001/07/15 22:33:49 1.6 @@ -13,7 +13,7 @@ my $from_url = '/input_filter.html'; my $to_url = '/TestFilter::input_msg::response'; -sub handler : InputFilterMessage { +sub handler : FilterConnectionHandler { my($filter, $bb, $mode, $readbytes) = @_; if ($bb->empty) { 1.12 +15 -17 modperl-2.0/xs/Apache/Filter/Apache__Filter.h Index: Apache__Filter.h =================================================================== RCS file: /home/cvs/modperl-2.0/xs/Apache/Filter/Apache__Filter.h,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- Apache__Filter.h 2001/05/07 02:05:02 1.11 +++ Apache__Filter.h 2001/07/15 22:33:50 1.12 @@ -100,24 +100,22 @@ char *pv = SvPV(ST(i), len); char *attribute = pv; + if (strnEQ(pv, "Filter", 6)) { + pv += 6; + } + switch (*pv) { - case 'I': - if (strnEQ(pv, "InputFilter", 11)) { - pv += 11; - switch (*pv) { - case 'B': - if (strEQ(pv, "Body")) { - *attrs |= MP_INPUT_FILTER_BODY; - trace_attr(); - continue; - } - case 'M': - if (strEQ(pv, "Message")) { - *attrs |= MP_INPUT_FILTER_MESSAGE; - trace_attr(); - continue; - } - } + case 'C': + if (strEQ(pv, "ConnectionHandler")) { + *attrs |= MP_FILTER_CONNECTION_HANDLER; + trace_attr(); + continue; + } + case 'R': + if (strEQ(pv, "RequestHandler")) { + *attrs |= MP_FILTER_REQUEST_HANDLER; + trace_attr(); + continue; } default: XPUSHs_mortal_pv(attribute);