httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dgau...@hyperreal.org
Subject cvs commit: apache-1.3/src/main buff.c
Date Sat, 07 Feb 1998 10:34:47 GMT
dgaudet     98/02/07 02:34:47

  Modified:    src/main buff.c
  Log:
  Sorry guys I know we're trying to get 1.3b4 rolled, but I really really
  really want chunking to work since it is affecting the deployment of
  HTTP/1.1.  I've stressed this patch a fair amount with a module I'll
  check in shortly.
  
  Two more chunking bugs:
  
  - start_chunk() called bflush() called start_chunk() caused chaos
  - if we ended up in the tail of bwrite() where a memcpy happens to copy
      the remainder, in certain boundary cases with chunking we would
      go past the end of the buffer
  
  Just generally clean up chunking a bit.  This would be a lot easier if
  chunking were just a layered I/O handler.
  
  Revision  Changes    Path
  1.63      +56 -47    apache-1.3/src/main/buff.c
  
  Index: buff.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/main/buff.c,v
  retrieving revision 1.62
  retrieving revision 1.63
  diff -u -r1.62 -r1.63
  --- buff.c	1998/02/03 20:00:58	1.62
  +++ buff.c	1998/02/07 10:34:43	1.63
  @@ -74,6 +74,13 @@
   #ifndef DEFAULT_BUFSIZE
   #define DEFAULT_BUFSIZE (4096)
   #endif
  +/* This must be enough to represent (DEFAULT_BUFSIZE - 3) in hex,
  + * plus two extra characters.
  + */
  +#ifndef CHUNK_HEADER_SIZE
  +#define CHUNK_HEADER_SIZE (5)
  +#endif
  +
   
   /* bwrite()s of greater than this size can result in a large_write() call,
    * which can result in a writev().  It's a little more work to set up the
  @@ -381,6 +388,8 @@
       }
   }
   
  +static int bflush_core(BUFF *fb);
  +
   /*
    * Start chunked encoding.
    *
  @@ -392,9 +401,6 @@
    */
   static void start_chunk(BUFF *fb)
   {
  -    char chunksize[16];		/* Big enough for practically anything */
  -    int chunk_header_size;
  -
       if (fb->outchunk != -1) {
   	/* already chunking */
   	return;
  @@ -404,26 +410,15 @@
   	return;
       }
   
  -    /* we know that the chunk header is going to take at least 3 bytes... */
  -    chunk_header_size = ap_snprintf(chunksize, sizeof(chunksize),
  -				 "%x\015\012", fb->bufsiz - fb->outcnt - 3);
       /* we need at least the header_len + at least 1 data byte
        * remember that we've overallocated fb->outbase so that we can always
        * fit the two byte CRLF trailer
        */
  -    if (fb->bufsiz - fb->outcnt < chunk_header_size + 1) {
  -	bflush(fb);
  +    if (fb->bufsiz - fb->outcnt < CHUNK_HEADER_SIZE + 1) {
  +	bflush_core(fb);
       }
  -    /* assume there's enough space now */
  -#ifdef CHARSET_EBCDIC
  -    /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */
  -    ebcdic2ascii(&fb->outbase[fb->outcnt], chunksize, chunk_header_size);
  -#else /*CHARSET_EBCDIC*/
  -    memcpy(&fb->outbase[fb->outcnt], chunksize, chunk_header_size);
  -#endif /*CHARSET_EBCDIC*/
       fb->outchunk = fb->outcnt;
  -    fb->outcnt += chunk_header_size;
  -    fb->outchunk_header_size = chunk_header_size;
  +    fb->outcnt += CHUNK_HEADER_SIZE;
   }
   
   
  @@ -433,13 +428,14 @@
   static void end_chunk(BUFF *fb)
   {
       int i;
  +    char *strp;
   
       if (fb->outchunk == -1) {
   	/* not chunking */
   	return;
       }
   
  -    if (fb->outchunk + fb->outchunk_header_size == fb->outcnt) {
  +    if (fb->outchunk + CHUNK_HEADER_SIZE == fb->outcnt) {
   	/* nothing was written into this chunk, and we can't write a 0 size
   	 * chunk because that signifies EOF, so just erase it
   	 */
  @@ -449,26 +445,24 @@
       }
   
       /* we know this will fit because of how we wrote it in start_chunk() */
  -    i = ap_snprintf((char *) &fb->outbase[fb->outchunk],
  -		    fb->outchunk_header_size,
  -		"%x", fb->outcnt - fb->outchunk - fb->outchunk_header_size);
  +    i = ap_snprintf((char *) &fb->outbase[fb->outchunk], CHUNK_HEADER_SIZE,
  +		"%x", fb->outcnt - fb->outchunk - CHUNK_HEADER_SIZE);
   
       /* we may have to tack some trailing spaces onto the number we just wrote
        * in case it was smaller than our estimated size.  We've also written
        * a \0 into the buffer with ap_snprintf so we might have to put a
        * \r back in.
        */
  -    i += fb->outchunk;
  -    while (fb->outbase[i] != '\015' && fb->outbase[i] != '\012') {
  -	fb->outbase[i++] = ' ';
  -    }
  -    if (fb->outbase[i] == '\012') {
  -	/* we overwrote the \r, so put it back */
  -	fb->outbase[i - 1] = '\015';
  +    strp = &fb->outbase[fb->outchunk + i];
  +    while (i < CHUNK_HEADER_SIZE - 2) {
  +	*strp++ = ' ';
  +	++i;
       }
  +    *strp++ = '\015';
  +    *strp = '\012';
   #ifdef CHARSET_EBCDIC
       /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */
  -    ebcdic2ascii(&fb->outbase[fb->outchunk], &fb->outbase[fb->outchunk],
fb->outchunk_header_size);
  +    ebcdic2ascii(&fb->outbase[fb->outchunk], &fb->outbase[fb->outchunk],
CHUNK_HEADER_SIZE);
   #endif /*CHARSET_EBCDIC*/
   
       /* tack on the trailing CRLF, we've reserved room for this */
  @@ -1156,7 +1150,7 @@
    */
   API_EXPORT(int) bwrite(BUFF *fb, const void *buf, int nbyte)
   {
  -    int i, nwr;
  +    int i, nwr, useable_bufsiz;
   #ifdef CHARSET_EBCDIC
       static char *cbuf = NULL;
       static int csize = 0;
  @@ -1259,8 +1253,13 @@
    * Note also that bcwrite never does a partial write if we're chunking,
    * so we're guaranteed to either end in an error state, or make it
    * out of this loop and call start_chunk() below.
  + *
  + * Remember we may not be able to use the entire buffer if we're
  + * chunking.
    */
  -    while (nbyte >= fb->bufsiz) {
  +    useable_bufsiz = fb->bufsiz;
  +    if (fb->flags & B_CHUNK) useable_bufsiz -= CHUNK_HEADER_SIZE;
  +    while (nbyte >= useable_bufsiz) {
   	i = bcwrite(fb, buf, nbyte);
   	if (i <= 0) {
   	    return nwr ? nwr : -1;
  @@ -1284,23 +1283,11 @@
       return nwr;
   }
   
  -/*
  - * Flushes the buffered stream.
  - * Returns 0 on success or -1 on error
  - */
  -API_EXPORT(int) bflush(BUFF *fb)
  +
  +static int bflush_core(BUFF *fb)
   {
       int i;
   
  -    if (!(fb->flags & B_WR) || (fb->flags & B_EOUT))
  -	return 0;
  -
  -    if (fb->flags & B_WRERR)
  -	return -1;
  -
  -    if (fb->flags & B_CHUNK)
  -	end_chunk(fb);
  -
       while (fb->outcnt > 0) {
   	i = write_with_errors(fb, fb->outbase, fb->outcnt);
   	if (i <= 0)
  @@ -1325,11 +1312,33 @@
   	    return -1;
       }
   
  -    if (fb->flags & B_CHUNK) {
  +    return 0;
  +}
  +
  +/*
  + * Flushes the buffered stream.
  + * Returns 0 on success or -1 on error
  + */
  +API_EXPORT(int) bflush(BUFF *fb)
  +{
  +    int ret;
  +
  +    if (!(fb->flags & B_WR) || (fb->flags & B_EOUT))
  +	return 0;
  +
  +    if (fb->flags & B_WRERR)
  +	return -1;
  +
  +    if (fb->flags & B_CHUNK)
  +	end_chunk(fb);
  +
  +    ret = bflush_core(fb);
  +
  +    if (ret == 0 && (fb->flags & B_CHUNK)) {
   	start_chunk(fb);
       }
   
  -    return 0;
  +    return ret;
   }
   
   /*
  
  
  

Mime
View raw message