--- mod_log_config.c	Mon Sep 16 22:43:36 2002
+++ /home/users/bojan/personal/httpd-2.0/mod_log_config.c	Thu Sep 19 15:33:52 2002
@@ -153,9 +153,11 @@
  *         'X' = connection aborted before the response completed.
  *         '+' = connection may be kept alive after the response is sent.
  *         '-' = connection will be closed after the response is sent.
-           (This directive was %...c in late versions of Apache 1.3, but
-            this conflicted with the historical ssl %...{var}c syntax.)
-*
+ *         (This directive was %...c in late versions of Apache 1.3, but
+ *         this conflicted with the historical ssl %...{var}c syntax.)
+ * %...I:  bytes received, including request and headers, cannot be zero
+ * %...O:  bytes sent, including headers, cannot be zero
+ *
  * The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can
  * indicate conditions for inclusion of the item (which will cause it
  * to be replaced with '-' if the condition is not met).  Note that
@@ -236,6 +238,8 @@
 static ap_log_writer_init *log_writer_init = ap_default_log_writer_init;
 static int buffered_logs = 0; /* default unbuffered */
 
+static const char logio_filter_name[] = "LOG_INPUT_OUTPUT";
+
 /* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is
  * guaranteed to be atomic when writing a pipe.  And PIPE_BUF >= 512
  * is guaranteed.  So we'll just guess 512 in the event the system
@@ -298,6 +302,16 @@
     char *condition_var;
 } config_log_state;
 
+/*****************************************************************
+ *
+ * Logging of input and output config ...
+ */
+
+typedef struct logio_config_t {
+    apr_off_t bytes_in;
+    apr_off_t bytes_out;
+} logio_config_t;
+
 /*
  * Format items...
  * Note that many of these could have ap_sprintfs replaced with static buffers.
@@ -620,6 +634,22 @@
     return "-";
 }
 
+static const char *log_bytes_in(request_rec *r, char *a)
+{
+    logio_config_t *cf = ap_get_module_config(r->connection->conn_config,
+                                              &log_config_module);
+
+    return cf ? apr_off_t_toa(r->pool, cf->bytes_in) : "-";
+}
+
+static const char *log_bytes_out(request_rec *r, char *a)
+{
+    logio_config_t *cf = ap_get_module_config(r->connection->conn_config,
+                                              &log_config_module);
+
+    return cf ? apr_off_t_toa(r->pool, cf->bytes_out) : "-";
+}
+
 /*****************************************************************
  *
  * Parsing the log format string
@@ -904,6 +934,8 @@
 {
     multi_log_state *mls = ap_get_module_config(r->server->module_config,
 						&log_config_module);
+    logio_config_t *cf = ap_get_module_config(r->connection->conn_config,
+                                              &log_config_module);
     config_log_state *clsarray;
     int i;
 
@@ -927,11 +959,62 @@
         }
     }
 
+    cf->bytes_in = cf->bytes_out = 0;
+
     return OK;
 }
 
 /*****************************************************************
  *
+ * Logging of input and output filters ...
+ */
+
+static apr_status_t logio_out_filter(ap_filter_t *f,
+                                     apr_bucket_brigade *bb) {
+    apr_off_t length;
+    logio_config_t *cf = ap_get_module_config(f->c->conn_config,
+                                              &log_config_module);
+
+    if (!cf) { /* Create config */
+        cf = apr_pcalloc(f->c->pool, sizeof(*cf));
+        ap_set_module_config(f->c->conn_config, &log_config_module, cf);
+    }
+
+    apr_brigade_length (bb, 0, &length);
+
+    if (length > 0)
+        cf->bytes_out += length;
+
+    return ap_pass_brigade(f->next, bb);
+}
+
+static apr_status_t logio_in_filter(ap_filter_t *f,
+                                    apr_bucket_brigade *bb,
+                                    ap_input_mode_t mode,
+                                    apr_read_type_e block,
+                                    apr_off_t readbytes) {
+    apr_off_t length;
+    apr_status_t status;
+    logio_config_t *cf = ap_get_module_config(f->c->conn_config,
+                                              &log_config_module);
+
+    status = ap_get_brigade(f->next, bb, mode, block, readbytes);
+
+    if (!cf) { /* Create config */
+        cf = apr_pcalloc(f->c->pool, sizeof(*cf));
+        ap_set_module_config(f->c->conn_config, &log_config_module, cf);
+    }
+
+    apr_brigade_length (bb, 0, &length);
+
+    if (length > 0)
+        cf->bytes_out += length;
+
+    return status;
+}
+
+/*****************************************************************
+ *
  * Module glue...
  */
 
@@ -1333,6 +1416,13 @@
     return rv;
 }
 
+static int logio_pre_conn(conn_rec *c) {
+    ap_add_input_filter(logio_filter_name, NULL, NULL, c);
+    ap_add_output_filter(logio_filter_name, NULL, NULL, c);
+
+    return OK;
+}
+
 static int log_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
 {
     static APR_OPTIONAL_FN_TYPE(ap_register_log_handler) *log_pfn_register;
@@ -1367,6 +1457,8 @@
         log_pfn_register(p, "T", log_request_duration, 1);
         log_pfn_register(p, "U", log_request_uri, 1);
         log_pfn_register(p, "s", log_status, 1);
+        log_pfn_register(p, "I", log_bytes_recv_all, 0);
+        log_pfn_register(p, "O", log_bytes_sent_all, 0);
     }
 
     return OK;
@@ -1374,6 +1466,7 @@
 
 static void register_hooks(apr_pool_t *p)
 {
+    ap_hook_pre_connection(logio_pre_conn, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_pre_config(log_pre_config,NULL,NULL,APR_HOOK_REALLY_FIRST);
     ap_hook_child_init(init_child,NULL,NULL,APR_HOOK_MIDDLE);
     ap_hook_open_logs(init_config_log,NULL,NULL,APR_HOOK_MIDDLE);
@@ -1389,6 +1482,11 @@
     APR_REGISTER_OPTIONAL_FN(ap_register_log_handler);
     APR_REGISTER_OPTIONAL_FN(ap_log_set_writer_init);
     APR_REGISTER_OPTIONAL_FN(ap_log_set_writer);
+
+    ap_register_input_filter(logio_filter_name, logio_in_filter, NULL,
+                             AP_FTYPE_NETWORK - 1);
+    ap_register_output_filter(logio_filter_name, logio_out_filter, NULL,
+                              AP_FTYPE_NETWORK - 1);
 }
 
 module AP_MODULE_DECLARE_DATA log_config_module =
@@ -1401,4 +1499,3 @@
     config_log_cmds,            /* command apr_table_t */
     register_hooks              /* register hooks */
 };
-
