fielding    97/01/25 14:37:17

  Modified:    src       buff.h buff.c http_main.c http_protocol.c
  Log:
  Fixed bug in bcwrite regarding failure to account for partial writes.
  Avoids calling bflush() when the client is pipelining requests.
  Remove unnecessary flushes from http_protocol.
  
  Submitted by: Dean Gaudet
  Reviewed by: Roy Fielding, Alexei Kosut
  
  Revision  Changes    Path
  1.10      +1 -0      apache/src/buff.h
  
  Index: buff.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/buff.h,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -C3 -r1.9 -r1.10
  *** buff.h    1997/01/01 18:10:15     1.9
  --- buff.h    1997/01/25 22:37:09     1.10
  ***************
  *** 120,125 ****
  --- 120,126 ----
    extern int bvputs(BUFF *fb, ...);
    extern int bprintf(BUFF *fb,const char *fmt,...);
    extern int vbprintf(BUFF *fb,const char *fmt,va_list vlist);
  + extern int btestread(BUFF *fb);
    
    /* Internal routines */
    extern int bflsbuf(int c, BUFF *fb);
  
  
  
  1.15      +72 -9     apache/src/buff.c
  
  Index: buff.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/buff.c,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -C3 -r1.14 -r1.15
  *** buff.c    1997/01/20 04:28:07     1.14
  --- buff.c    1997/01/25 22:37:10     1.15
  ***************
  *** 402,407 ****
  --- 402,438 ----
    }
    
    /*
  +  * Tests if there is data to be read.  Returns 0 if there is data,
  +  * -1 otherwise.
  +  */
  + int
  + btestread(BUFF *fb)
  + {
  +     fd_set fds;
  +     struct timeval tv;
  +     int rv;
  + 
  +     /* the simple case, we've already got data in the buffer */
  +     if( fb->incnt ) {
  +     return( 0 );
  +     }
  + 
  +     /* otherwise see if the descriptor would block if we try to read it */
  +     do {
  +     FD_ZERO( &fds );
  +     FD_SET( fb->fd_in, &fds );
  +     tv.tv_sec = 0;
  +     tv.tv_usec = 0;
  + #ifdef HPUX
  +     rv = select( fb->fd_in + 1, (int *)&fds, NULL, NULL, &tv );
  + #else
  +     rv = select( fb->fd_in + 1, &fds, NULL, NULL, &tv );
  + #endif
  +     } while( rv < 0 && errno == EINTR );
  +     return( rv == 1 ? 0 : -1 );
  + }
  + 
  + /*
     * Skip data until a linefeed character is read
     * Returns 1 on success, 0 if no LF found, or -1 on error
     */
  ***************
  *** 469,474 ****
  --- 500,533 ----
        else return buf[0];
    }
    
  + 
  + /*
  +  * When doing chunked encodings we really have to write everything in the
  +  * chunk before proceeding onto anything else.  This routine either writes
  +  * nbytes and returns 0 or returns -1 indicating a failure.
  +  *
  +  * This is *seriously broken* if used on a non-blocking fd.  It will poll.
  +  */
  + static int
  + write_it_all( int fd, const void *buf, int nbyte ) {
  + 
  +     int i;
  + 
  +     while( nbyte > 0 ) {
  +     i = write( fd, buf, nbyte );
  +     if( i == -1 ) {
  +         if( errno != EAGAIN && errno != EINTR ) {
  +             return( -1 );
  +         }
  +     } else {
  +         nbyte -= i;
  +         buf = i + (const char *)buf;
  +     }
  +     }
  +     return( 0 );
  + }
  + 
  + 
    /*
     * A hook to write() that deals with chunking. This is really a protocol-
     * level issue, but we deal with it here because it's simpler; this is
  ***************
  *** 476,493 ****
     * 2.0, using something like sfio stacked disciplines or BSD's funopen().
     */
    int bcwrite(BUFF *fb, const void *buf, int nbyte) {
  -     int r;
    
        if (fb->flags & B_CHUNK) {
        char chunksize[16];     /* Big enough for practically anything */
    
        ap_snprintf(chunksize, sizeof(chunksize), "%x\015\012", nbyte);
  !     write(fb->fd, chunksize, strlen(chunksize));
        }
  !     r = write(fb->fd, buf, nbyte);
  !     if ((r > 0) && (fb->flags & B_CHUNK))
  !     write(fb->fd, "\015\012", 2);
  !     return r;
    }
    
    /*
  --- 535,557 ----
     * 2.0, using something like sfio stacked disciplines or BSD's funopen().
     */
    int bcwrite(BUFF *fb, const void *buf, int nbyte) {
    
        if (fb->flags & B_CHUNK) {
        char chunksize[16];     /* Big enough for practically anything */
    
        ap_snprintf(chunksize, sizeof(chunksize), "%x\015\012", nbyte);
  !     if( write_it_all(fb->fd, chunksize, strlen(chunksize)) == -1 ) {
  !         return( -1 );
  !     }
  !     if( write_it_all(fb->fd, buf, nbyte) == -1 ) {
  !         return( -1 );
  !     }
  !     if( write_it_all(fb->fd, "\015\012", 2) == -1 ) {
  !         return( -1 );
  !     }
  !     return( nbyte );
        }
  !     return( write(fb->fd, buf, nbyte) );
    }
    
    /*
  ***************
  *** 573,579 ****
    /* we have emptied the file buffer. Now try to write the data from the
     * original buffer until there is less than bufsiz left
     */
  !     while (nbyte > fb->bufsiz)
        {
        do i = bcwrite(fb, buf, nbyte);
        while (i == -1 && errno == EINTR);
  --- 637,643 ----
    /* we have emptied the file buffer. Now try to write the data from the
     * original buffer until there is less than bufsiz left
     */
  !     while (nbyte >= fb->bufsiz)
        {
        do i = bcwrite(fb, buf, nbyte);
        while (i == -1 && errno == EINTR);
  ***************
  *** 611,617 ****
    int
    bflush(BUFF *fb)
    {
  !     int i, j;
    
        if (!(fb->flags & B_WR) || (fb->flags & B_EOUT)) return 0;
    
  --- 675,681 ----
    int
    bflush(BUFF *fb)
    {
  !     int i;
    
        if (!(fb->flags & B_WR) || (fb->flags & B_EOUT)) return 0;
    
  ***************
  *** 620,626 ****
        while (fb->outcnt > 0)
        {
    /* the buffer must be full */
  -     j = fb->outcnt;
        do i = bcwrite(fb, fb->outbase, fb->outcnt);
        while (i == -1 && errno == EINTR);
        if (i > 0) fb->bytes_sent += i;
  --- 684,689 ----
  
  
  
  1.113     +5 -2      apache/src/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_main.c,v
  retrieving revision 1.112
  retrieving revision 1.113
  diff -C3 -r1.112 -r1.113
  *** http_main.c       1997/01/25 20:28:19     1.112
  --- http_main.c       1997/01/25 22:37:11     1.113
  ***************
  *** 1675,1681 ****
            if (r) increment_counts(child_num,r,1);
    #endif
        while (r && current_conn->keepalive) {
  !         bflush(conn_io);
            destroy_pool(r->pool);
            (void)update_child_status (child_num, SERVER_BUSY_KEEPALIVE,
             (request_rec*)NULL);
  --- 1675,1684 ----
            if (r) increment_counts(child_num,r,1);
    #endif
        while (r && current_conn->keepalive) {
  !         /* If there's no request waiting for us to read then flush the
  !          * socket.  This is to avoid tickling a bug in older Netscape
  !          * clients. */
  !         if( btestread(conn_io) == -1 ) bflush(conn_io);
            destroy_pool(r->pool);
            (void)update_child_status (child_num, SERVER_BUSY_KEEPALIVE,
             (request_rec*)NULL);
  ***************
  *** 2150,2156 ****
        if (r) process_request (r); /* else premature EOF (ignore) */
    
            while (r && conn->keepalive) {
  !         bflush(cio);
            destroy_pool(r->pool);
                r = read_request (conn);
                if (r) process_request (r);
  --- 2153,2159 ----
        if (r) process_request (r); /* else premature EOF (ignore) */
    
            while (r && conn->keepalive) {
  !         if( btestread(cio) == -1 ) bflush(cio);
            destroy_pool(r->pool);
                r = read_request (conn);
                if (r) process_request (r);
  
  
  
  1.92      +0 -2      apache/src/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_protocol.c,v
  retrieving revision 1.91
  retrieving revision 1.92
  diff -C3 -r1.91 -r1.92
  *** http_protocol.c   1997/01/20 04:28:09     1.91
  --- http_protocol.c   1997/01/25 22:37:12     1.92
  ***************
  *** 1371,1378 ****
            o+=w;
            }
        }
  - 
  -     if (length > 0) bflush(c->client);
        
        SET_BYTES_SENT(r);
        return total_bytes_sent;
  --- 1371,1376 ----
  
  
  

Reply via email to