I would like to write an httpd module with output filters to record when a
client sends the first byte of an HTTP request and when send the last. After
looking a while through the existing filters in the httpd source code I was
able
to accomplish that but unfortunately it doesn't work for keep-alive
connections;
the client 'first byte time' would remain the 'connection establish' time.
Any help on this would be highly appreciated!
In a sort of pseudo-code this is what I did:
<pre>
<code>
static int pre_conn(conn_rec *c, void *csd) {
my_config_t *config = apr_pcalloc(c->pool, sizeof(*config));
ap_set_module_config(c->conn_config, &my_module, config);
ap_add_input_filter(my_filter_name, NULL, NULL, c);
ap_add_output_filter(my_filter_name, NULL, NULL, c);
return OK;
}
/* Output filter - records the 'last byte in' time */
static apr_status_t out_filter(ap_filter_t *f, apr_bucket_brigade *bb) {
conn_rec *c = f->c;
apr_bucket *b = APR_BRIGADE_LAST(bb);
/* End of data, make sure we flush */
if (APR_BUCKET_IS_EOS(b)) {
APR_BRIGADE_INSERT_TAIL(bb,apr_bucket_flush_create(f->c->bucket_alloc));
APR_BUCKET_REMOVE(b);
apr_bucket_destroy(b);
}
apr_status_t ret = ap_pass_brigade(f->next, bb);
// save 'last byte in' time
return ret;
}
static apr_status_t in_filter_start(ap_filter_t *f, apr_bucket_brigade *bb,
ap_input_mode_t mode, apr_read_type_e block, apr_off_t read_bytes) {
apr_bucket *b;
conn_rec *c = f->c;
apr_status_t status;
// save the 'first time in' byte
status = ap_get_brigade(f->next, bb, mode, block, read_bytes);
if (status == APR_SUCCESS) {
for (b = APR_BRIGADE_FIRST(bb); b != APR_BRIGADE_SENTINEL(bb); b =
APR_BUCKET_NEXT(b)) {
;
}
}
return status;
}
</code>
</pre>
I registered my filters in the following way:
ap_hook_pre_connection(pre_conn, NULL, NULL, APR_HOOK_MIDDLE);
ap_register_input_filter(my_filter_name, in_filter_start,NULL,
AP_FTYPE_CONNECTION + 2 ); ap_register_output_filter(my_filter_name,
out_filter, NULL, AP_FTYPE_NETWORK - 1);
Thanks,
Alin