]> granicus.if.org Git - apache/commitdiff
Input filters and ap_get_brigade() now have a input mode parameter
authorJeff Trawick <trawick@apache.org>
Sat, 21 Oct 2000 13:20:36 +0000 (13:20 +0000)
committerJeff Trawick <trawick@apache.org>
Sat, 21 Oct 2000 13:20:36 +0000 (13:20 +0000)
(blocking, non-blocking, peek) instead of a length parameter.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86684 13f79535-47bb-0310-9956-ffa450edef68

include/http_protocol.h
include/util_filter.h
modules/http/http_core.c
modules/http/http_protocol.c
server/util_filter.c

index 1d76e1d32bee6fc5b74e492df948a2ca7ea1d14b..eff978a9f5f379b5f52d2fbe6efac5ce147f46ec 100644 (file)
@@ -529,8 +529,8 @@ AP_DECLARE(int) ap_method_number_of(const char *method);
  */
 AP_DECLARE(const char *) ap_method_name_of(int methnum);
 
-int http_filter(ap_filter_t *f, ap_bucket_brigade *b, apr_ssize_t length);
-apr_status_t dechunk_filter(ap_filter_t *f, ap_bucket_brigade *b, apr_ssize_t length);
+apr_status_t http_filter(ap_filter_t *f, ap_bucket_brigade *b, ap_input_mode_t mode);
+apr_status_t dechunk_filter(ap_filter_t *f, ap_bucket_brigade *b, ap_input_mode_t mode);
 
   /* Hooks */
   /*
index 8a9b95939098f0b9856f19b58b2ff0ea32d1f4d2..edcc4eb636abb3bbbbe089c065231bc95c90f5bc 100644 (file)
@@ -74,11 +74,29 @@ extern "C" {
 #define AP_NOBODY_WROTE         -1
 #define AP_NOBODY_READ          -2
 
-/* Input filtering macros */
-#define AP_GET_LINE                0  /* Get one line from the next filter */
-#define AP_GET_ANY_AMOUNT         -1  /* Get as much data as the next filter
-                                       * is willing to give up.
-                                       */
+/* ap_input_mode_t - input filtering modes 
+ * 
+ * AP_MODE_BLOCKING
+ *
+ *   The filter shouldn't return until data is received or EOF is hit or an error
+ *   occurs.
+ *
+ * AP_MODE_NONBLOCKING
+ *
+ *   The filter should process any available data/status as normal, but will not 
+ *   wait for additional data.
+ *
+ * AP_MODE_PEEK
+ *
+ *   The filter should return APR_SUCCESS if data is available or APR_EOF 
+ *   otherwise.  The filter must not return any buckets of data.  Data returned
+ *   on a subsequent call, when mode is AP_MODE_BLOCKING or AP_MODE_NONBLOCKING.
+ */
+typedef enum {
+    AP_MODE_BLOCKING,
+    AP_MODE_NONBLOCKING,
+    AP_MODE_PEEK
+} ap_input_mode_t;
 
 /*
  * FILTER CHAIN
@@ -132,7 +150,8 @@ typedef struct ap_filter_t ap_filter_t;
  * The return value of a filter should be an APR status value.
  */
 typedef apr_status_t (*ap_out_filter_func)(ap_filter_t *f, ap_bucket_brigade *b);
-typedef apr_status_t (*ap_in_filter_func)(ap_filter_t *f, ap_bucket_brigade *b, apr_ssize_t length);
+typedef apr_status_t (*ap_in_filter_func)(ap_filter_t *f, ap_bucket_brigade *b, 
+                                          ap_input_mode_t mode);
 typedef union ap_filter_func {
     ap_out_filter_func out_func;
     ap_in_filter_func in_func;
@@ -243,19 +262,12 @@ struct ap_filter_t {
  * filter doesn't write to the network, then AP_NOBODY_READ is returned.
  * @param filter The next filter in the chain
  * @param bucket The current bucket brigade
- * @param length The maximum amount of data to be returned from the next
- *               lowest filter.  If filter a requests 15 bytes
- *               from the filter b, that doesn't stop the b
- *               from requesting 30 bytes from filter c.  It just
- *               stops b from returning more that 15 bytes to a.  The other
- *               15 must be stored by b.  A value of AP_GET_LINE (0) tells 
- *               the filter to only ever return a single line.  A value of
- *               AP_GET_ANY_AMOUNT (-1) tells a filter to return everything
- *               it has.
+ * @param mode   AP_MODE_BLOCKING, AP_MODE_NONBLOCKING, or AP_MODE_PEEK
  * @return apr_status_t value
- * @deffunc apr_status_t ap_get_brigade(ap_filter_t *filter, ap_bucket_brigade *bucket, apr_ssize_t length)
+ * @deffunc apr_status_t ap_get_brigade(ap_filter_t *filter, ap_bucket_brigade *bucket, ap_input_mode_t mode)
  */
-AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *filter, ap_bucket_brigade *bucket, apr_ssize_t length);
+AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *filter, ap_bucket_brigade *bucket, 
+                                        ap_input_mode_t mode);
 
 /**
  * Pass the current bucket brigade down to the next filter on the filter
index 6db7ebe7318e76bc45edd92bab0c92b213a07b7d..bd914f749c1fe0970a7f38f3096c172a68a195c7 100644 (file)
@@ -3327,12 +3327,7 @@ static apr_status_t chunk_filter(ap_filter_t *f, ap_bucket_brigade *b)
     return APR_SUCCESS;
 }
 
-/* This function only understands a length of AP_GET_ANY_AMOUNT.  It will
- * ignore length values and always return the entire brigade.  This is
- * pretty safe to do, because we know there always needs to be an intervening
- * filter just above this that will only make requests for AP_GET_ANY_AMOUNT
- */
-static int core_input_filter(ap_filter_t *f, ap_bucket_brigade *b, apr_ssize_t length)
+static int core_input_filter(ap_filter_t *f, ap_bucket_brigade *b, ap_input_mode_t mode)
 {
     ap_bucket *e;
     
@@ -3359,7 +3354,7 @@ typedef struct CORE_OUTPUT_FILTER_CTX {
     ap_bucket_brigade *b;
 } core_output_filter_ctx_t;
 #define MAX_IOVEC_TO_WRITE 16
-static int core_output_filter(ap_filter_t *f, ap_bucket_brigade *b)
+static apr_status_t core_output_filter(ap_filter_t *f, ap_bucket_brigade *b)
 {
     apr_status_t rv;
     ap_bucket_brigade *more = NULL;
index 2b798ba37d742e5d89cea0bc9584754f808f769c..5e8e2ff2a2dca23d46e0280e798189b8b593e9ad 100644 (file)
@@ -850,7 +850,7 @@ static long get_chunk_size(char *);
 static int getline(char *s, int n, request_rec *r, int fold);
 
 apr_status_t dechunk_filter(ap_filter_t *f, ap_bucket_brigade *bb,
-                            apr_ssize_t length)
+                            ap_input_mode_t mode)
 {
     apr_status_t rv;
     struct dechunk_ctx *ctx = f->ctx;
@@ -907,7 +907,7 @@ apr_status_t dechunk_filter(ap_filter_t *f, ap_bucket_brigade *bb,
     if (ctx->state == WANT_BODY) {
         /* Tell http_filter() how many bytes to deliver. */
         f->c->remain = ctx->chunk_size - ctx->bytes_delivered;
-        if ((rv = ap_get_brigade(f->next, bb, 999)) != APR_SUCCESS) {
+        if ((rv = ap_get_brigade(f->next, bb, mode)) != APR_SUCCESS) {
             return rv;
         }
         /* Walk through the body, accounting for bytes, and removing an eos bucket if
@@ -935,7 +935,7 @@ typedef struct http_filter_ctx {
     ap_bucket_brigade *b;
 } http_ctx_t;
 
-apr_status_t http_filter(ap_filter_t *f, ap_bucket_brigade *b, apr_ssize_t length)
+apr_status_t http_filter(ap_filter_t *f, ap_bucket_brigade *b, ap_input_mode_t mode)
 {
 #define ASCII_LF '\012'
     ap_bucket *e;
@@ -948,15 +948,27 @@ apr_status_t http_filter(ap_filter_t *f, ap_bucket_brigade *b, apr_ssize_t lengt
     if (!ctx) {
         f->ctx = ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));
         ctx->b = ap_brigade_create(f->c->pool);
-        if ((rv = ap_get_brigade(f->next, ctx->b, AP_GET_ANY_AMOUNT)) != APR_SUCCESS) {
-            return rv;
-        }
     }
-    else {
+
+    if (mode == AP_MODE_PEEK) {
+        /* XXX make me *try* to read from the network if AP_BRIGADE_EMPTY().
+         * For now, we can't do a non-blocking read so we bypass this.
+         *
+         * Also, note that in the cases where another request can be read now
+         * without blocking, it is likely already in our brigadet, so this hack 
+         * isn't so bad after all.
+         */
         if (AP_BRIGADE_EMPTY(ctx->b)) {
-            if ((rv = ap_get_brigade(f->next, ctx->b, AP_GET_LINE)) != APR_SUCCESS) {
-                return rv;
-            }
+            return APR_EOF;
+        }
+        else {
+            return APR_SUCCESS;
+        }
+    }
+
+    if (AP_BRIGADE_EMPTY(ctx->b)) {
+        if ((rv = ap_get_brigade(f->next, ctx->b, mode)) != APR_SUCCESS) {
+            return rv;
         }
     }
 
@@ -1053,7 +1065,7 @@ static int getline(char *s, int n, request_rec *r, int fold)
 
     while (1) {
         if (AP_BRIGADE_EMPTY(b)) {
-            if (ap_get_brigade(c->input_filters, b, AP_GET_LINE) != APR_SUCCESS ||
+            if (ap_get_brigade(c->input_filters, b, AP_MODE_BLOCKING) != APR_SUCCESS ||
                 AP_BRIGADE_EMPTY(b)) {
                 return -1;
             }
index 41bcb84fc673e571ef9e2662f254c634c87cb048..85780a04f61d36cf9452279ef9fd87b8c37085f1 100644 (file)
@@ -195,11 +195,11 @@ AP_DECLARE(void) ap_add_output_filter(const char *name, void *ctx,
  * save data off to the side should probably create their own temporary
  * brigade especially for that use.
  */
-AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next, 
-                                      ap_bucket_brigade *bb, apr_ssize_t length)
+AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next, ap_bucket_brigade *bb, 
+                                        ap_input_mode_t mode)
 {
     if (next) {
-        return next->frec->filter_func.in_func(next, bb, length);
+        return next->frec->filter_func.in_func(next, bb, mode);
     }
     return AP_NOBODY_READ;
 }