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);