httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r..@locus.apache.org
Subject cvs commit: apache-2.0/src/main http_protocol.c
Date Sat, 07 Oct 2000 05:41:59 GMT
rbb         00/10/06 22:41:59

  Modified:    src/include httpd.h
               src/main http_protocol.c
  Log:
  The newest incarnation of http_filter.  This is far from perfect, but it
  is a step in the right direction.  The idea is that the http_filter knows
  about the http protocol.  So, it uses that knowledge to discover HTTP
  request headers, and sends those headers up to getline.  However, it keeps
  the request body saved in it's ctx pointer.
  
  Later, when ap_get_client_block is called, we have set the remaining field
  in the conn_rec.  This tells the http_filter how much of the remaining
  data is request body, and how much isn't.  So, the http_filter can return
  the request body unparsed up throught ap_get_client_block.
  
  This doesn't even try to work with chunked input data, and there are still
  some other bugs in it, but it works for small-ish files in my tests, and
  it lets other people play with the concept of input filters.  I will try
  to play with this more, but others should feel free to hack around in it
  too.
  
  Revision  Changes    Path
  1.93      +3 -0      apache-2.0/src/include/httpd.h
  
  Index: httpd.h
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/include/httpd.h,v
  retrieving revision 1.92
  retrieving revision 1.93
  diff -u -r1.92 -r1.93
  --- httpd.h	2000/10/05 22:34:50	1.92
  +++ httpd.h	2000/10/07 05:41:58	1.93
  @@ -887,6 +887,9 @@
       /** A list of output filters to be used for this connection
        *  @defvar ap_filter_t *filters */
       struct ap_filter_t *output_filters;
  +    /** bytes left to read in the current request body */
  +    long remaining;
  +
   };
   
   /* Per-vhost config... */
  
  
  
  1.148     +86 -14    apache-2.0/src/main/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
  retrieving revision 1.147
  retrieving revision 1.148
  diff -u -r1.147 -r1.148
  --- http_protocol.c	2000/10/06 16:41:30	1.147
  +++ http_protocol.c	2000/10/07 05:41:59	1.148
  @@ -856,6 +856,10 @@
       return AP_HTTP_METHODS[methnum];
   }
   
  +typedef struct http_filter_ctx {
  +    ap_bucket_brigade *b;
  +    int c_len;
  +} http_ctx_t;
   int http_filter(ap_filter_t *f, ap_bucket_brigade *b)
   {
   #define ASCII_CR '\015'
  @@ -864,8 +868,47 @@
       char *buff;
       int length;
       char *pos;
  +    int state = 0;
  +    http_ctx_t *ctx = f->ctx;
  +    ap_bucket_brigade *bb;
  +
  +
  +    if (!ctx) {
  +        f->ctx = ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));
  +        ap_get_brigade(f->next, b);
  +    }
  +    else {
  +        if (ctx->b) {
  +            AP_BRIGADE_CONCAT(b, ctx->b);
  +            ctx->b = NULL;
  +        }
  +        else {
  +            ap_get_brigade(f->next, b);
  +        }
  +    }
   
  -    ap_get_brigade(f->next, b);
  +    if (f->c->remaining > 0) {
  +        int remain = f->c->remaining;
  +        e = AP_BRIGADE_FIRST(b);
  +        while (remain > e->length && e != AP_BRIGADE_SENTINEL(b)) {
  +            remain -= e->length;
  +            e = AP_BUCKET_NEXT(e);
  +        }
  +        if (e != AP_BRIGADE_SENTINEL(b)) {
  +            if (remain <= e->length) {
  +                e->split(e, remain);
  +                remain = 0;
  +            }
  +            bb = ap_brigade_split(b, AP_BUCKET_NEXT(e));
  +            f->c->remaining = remain;
  +            ctx->b = bb;
  +            return length;
  +        }
  +        else {
  +            ctx->b = NULL;
  +            return length;
  +        }
  +    }
   
       AP_BRIGADE_FOREACH(e, b) {
   
  @@ -873,11 +916,28 @@
   
           pos = buff + 1;
           while (pos < buff + length) {
  +
  +            /* We are at the start of one line, but it actually has data. */
  +            if ((*pos != ASCII_LF) && (*pos != ASCII_CR)) {
  +                state = 0;
  +            }
  +            else {
  +                if (*pos == ASCII_LF) {
  +                    state++;
  +                }
  +            }
  +            
               if ((*pos == ASCII_LF) && (*(pos - 1) == ASCII_CR)) {
                   *(pos - 1) = ASCII_LF;
                   *pos = '\0';
               }
               pos++;
  +            if (state == 2) {
  +                e->split(e, pos - buff);
  +                bb = ap_brigade_split(b, AP_BUCKET_NEXT(e));
  +                ctx->b = bb;
  +                return length;
  +            }
           }
       }
       return APR_SUCCESS;
  @@ -2266,6 +2326,7 @@
           }
   
           r->remaining = atol(lenp);
  +        r->connection->remaining = r->remaining;
       }
   
       if ((r->read_body == REQUEST_NO_BODY) &&
  @@ -2378,20 +2439,31 @@
           const char *tempbuf;
   
           len_to_read = (r->remaining > bufsiz) ? bufsiz : r->remaining;
  -        if (AP_BRIGADE_EMPTY(r->connection->input_data)) {
  -            apr_getsocketopt(r->connection->client->bsock, APR_SO_TIMEOUT, &timeout);
  -            apr_setsocketopt(r->connection->client->bsock, APR_SO_TIMEOUT, 0);
  -            rv = ap_get_brigade(r->connection->input_filters, r->connection->input_data);

  -            apr_setsocketopt(r->connection->client->bsock, APR_SO_TIMEOUT, timeout);
  -        }
  -        if (AP_BRIGADE_EMPTY(r->connection->input_data)) {
  -            if (rv != APR_SUCCESS) {
  -                r->connection->keepalive = -1;
  -                return -1;
  +
  +        do {
  +            if (AP_BRIGADE_EMPTY(r->connection->input_data)) {
  +                apr_getsocketopt(r->connection->client->bsock, APR_SO_TIMEOUT,
&timeout);
  +                apr_setsocketopt(r->connection->client->bsock, APR_SO_TIMEOUT,
0);
  +                rv = ap_get_brigade(r->connection->input_filters, r->connection->input_data);

  +                apr_setsocketopt(r->connection->client->bsock, APR_SO_TIMEOUT,
timeout);
               }
  -            return 0;
  -        }
  -        b = AP_BRIGADE_FIRST(r->connection->input_data);
  +            if (AP_BRIGADE_EMPTY(r->connection->input_data)) {
  +                if (rv != APR_SUCCESS) {
  +                    r->connection->keepalive = -1;
  +                    return -1;
  +                }
  +                return 0;
  +            }
  +            b = AP_BRIGADE_FIRST(r->connection->input_data);
  +            
  +            while (b->length == 0 && b != AP_BRIGADE_SENTINEL(r->connection->input_data))
{
  +                ap_bucket *e = b;
  +                b = AP_BUCKET_NEXT(e);
  +                AP_BUCKET_REMOVE(e);
  +                e->destroy(e);
  +            }
  +        } while (AP_BRIGADE_EMPTY(r->connection->input_data));
  +
           len_read = len_to_read;
           rv = b->read(b, &tempbuf, &len_read, 0);
           if (len_to_read < b->length) {
  
  
  

Mime
View raw message