httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Roy Fielding <field...@hyperreal.com>
Subject cvs commit: apache/src CHANGES buff.h buff.c http_main.c http_protocol.c
Date Thu, 30 Jan 1997 02:43:03 GMT
fielding    97/01/29 18:43:02

  Modified:    src       CHANGES buff.h buff.c http_main.c http_protocol.c
  Log:
  Improved buffered output to the client by delaying the flush decision
  until the BUFF code is actually about to read the next request.
  This fixes a problem introduced in 1.2b5 with clients that send
  an extra CRLF after a POST request.
  
  Submitted by: Dean Gaudet
  Reviewed by: Roy Fielding
  
  Revision  Changes    Path
  1.140     +6 -1      apache/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/apache/src/CHANGES,v
  retrieving revision 1.139
  retrieving revision 1.140
  diff -C3 -r1.139 -r1.140
  *** CHANGES	1997/01/30 02:27:06	1.139
  --- CHANGES	1997/01/30 02:42:56	1.140
  ***************
  *** 1,6 ****
  ! Changes with Apache 1.2b6
    
      *) Continue persistent connection after 304 response. [Dean Gaudet]
    
    Changes with Apache 1.2b6
    
  --- 1,11 ----
  ! Changes with Apache 1.2b7
    
      *) Continue persistent connection after 304 response. [Dean Gaudet]
  + 
  +   *) Improved buffered output to the client by delaying the flush decision
  +      until the BUFF code is actually about to read the next request.
  +      This fixes a problem introduced in 1.2b5 with clients that send
  +      an extra CRLF after a POST request. [Dean Gaudet]
    
    Changes with Apache 1.2b6
    
  
  
  
  1.11      +2 -1      apache/src/buff.h
  
  Index: buff.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/buff.h,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -C3 -r1.10 -r1.11
  *** buff.h	1997/01/25 22:37:09	1.10
  --- buff.h	1997/01/30 02:42:57	1.11
  ***************
  *** 68,73 ****
  --- 68,75 ----
    #define B_ERROR (48)
    /* Use chunked writing */
    #define B_CHUNK (64)
  + /* bflush() if a read would block */
  + #define B_SAFEREAD (128)
    
    typedef struct buff_struct BUFF;
    
  ***************
  *** 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);
  --- 122,127 ----
  
  
  
  1.16      +57 -49    apache/src/buff.c
  
  Index: buff.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/buff.c,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -C3 -r1.15 -r1.16
  *** buff.c	1997/01/25 22:37:10	1.15
  --- buff.c	1997/01/30 02:42:57	1.16
  ***************
  *** 175,193 ****
    }
    
    /*
  !  * Set a flag on (1) or off (0). Currently, these flags work
  !  * as a function of the bcwrite() function, so we make sure to
  !  * flush before setting them one way or the other; otherwise
  !  * writes could end up with the wrong flag.
     */
    int bsetflag(BUFF *fb, int flag, int value)
    {
  !     bflush(fb);
        if (value) fb->flags |= flag;
        else fb->flags &= ~flag;
        return value;
    }
    
    /*
     * Read up to nbyte bytes into buf.
     * If fewer than byte bytes are currently available, then return those.
  --- 175,239 ----
    }
    
    /*
  !  * Set a flag on (1) or off (0).
     */
    int bsetflag(BUFF *fb, int flag, int value)
    {
  !     if( flag & B_CHUNK ) {
  ! 	/*
  ! 	 * This shouldn't be true for much longer -djg
  ! 	 * Currently, these flags work
  ! 	 * as a function of the bcwrite() function, so we make sure to
  ! 	 * flush before setting them one way or the other; otherwise
  ! 	 * writes could end up with the wrong flag.
  ! 	 */
  ! 	bflush(fb);
  !     }
        if (value) fb->flags |= flag;
        else fb->flags &= ~flag;
        return value;
    }
    
  + 
  + /*
  +  * This is called instead of read() everywhere in here.  It implements
  +  * the B_SAFEREAD functionality -- which is to force a flush() if a read()
  +  * would block.  It also deals with the EINTR errno result from read().
  +  * return code is like read() except EINTR is eliminated.
  +  */
  + static int
  + saferead( BUFF *fb, void *buf, int nbyte )
  + {
  +     int rv;
  + 
  +     if( fb->flags & B_SAFEREAD ) {
  + 	fd_set fds;
  + 	struct timeval tv;
  + 
  + 	/* test for a block */
  + 	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 );
  + 	/* treat any error as if it would block as well */
  + 	if( rv != 1 ) {
  + 	    bflush(fb);
  + 	}
  +     }
  +     do {
  + 	rv = read( fb->fd_in, buf, nbyte );
  +     } while ( rv == -1 && errno == EINTR );
  +     return( rv );
  + }
  + 
  + 
    /*
     * Read up to nbyte bytes into buf.
     * If fewer than byte bytes are currently available, then return those.
  ***************
  *** 204,211 ****
        if (!(fb->flags & B_RD))
        {
    /* Unbuffered reading */
  ! 	do i = read(fb->fd_in, buf, nbyte);
  ! 	while (i == -1 && errno == EINTR);
    	if (i == -1 && errno != EAGAIN) doerror(fb, B_RD);
    	return i;
        }
  --- 250,256 ----
        if (!(fb->flags & B_RD))
        {
    /* Unbuffered reading */
  ! 	i = saferead( fb, buf, nbyte );
    	if (i == -1 && errno != EAGAIN) doerror(fb, B_RD);
    	return i;
        }
  ***************
  *** 233,240 ****
        if (nbyte >= fb->bufsiz)
        {
    /* read directly into buffer */
  ! 	do i = read(fb->fd_in, buf, nbyte);
  ! 	while (i == -1 && errno == EINTR);
    	if (i == -1)
    	{
    	    if (nrd == 0)
  --- 278,284 ----
        if (nbyte >= fb->bufsiz)
        {
    /* read directly into buffer */
  ! 	i = saferead( fb, buf, nbyte );
    	if (i == -1)
    	{
    	    if (nrd == 0)
  ***************
  *** 248,255 ****
        {
    /* read into hold buffer, then memcpy */
    	fb->inptr = fb->inbase;
  ! 	do i = read(fb->fd_in, fb->inptr, fb->bufsiz);
  ! 	while (i == -1 && errno == EINTR);
    	if (i == -1)
    	{
    	    if (nrd == 0)
  --- 292,298 ----
        {
    /* read into hold buffer, then memcpy */
    	fb->inptr = fb->inbase;
  ! 	i = saferead( fb, fb->inptr, fb->bufsiz );
    	if (i == -1)
    	{
    	    if (nrd == 0)
  ***************
  *** 310,317 ****
    	    fb->inptr = fb->inbase;
    	    fb->incnt = 0;
    	    if (fb->flags & B_EOF) break;
  ! 	    do i = read(fb->fd_in, fb->inptr, fb->bufsiz);
  ! 	    while (i == -1 && errno == EINTR);
    	    if (i == -1)
    	    {
    		buff[ct] = '\0';
  --- 353,359 ----
    	    fb->inptr = fb->inbase;
    	    fb->incnt = 0;
    	    if (fb->flags & B_EOF) break;
  ! 	    i = saferead( fb, fb->inptr, fb->bufsiz );
    	    if (i == -1)
    	    {
    		buff[ct] = '\0';
  ***************
  *** 381,389 ****
            if (fb->flags & B_EOF)
                return 0;
    
  !         do {
  !             i = read(fb->fd_in, fb->inptr, fb->bufsiz);
  !         } while (i == -1 && errno == EINTR);
    
            if (i == -1) {
                if (errno != EAGAIN)
  --- 423,429 ----
            if (fb->flags & B_EOF)
                return 0;
    
  ! 	i = saferead( fb, fb->inptr, fb->bufsiz );
    
            if (i == -1) {
                if (errno != EAGAIN)
  ***************
  *** 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
     */
  --- 442,447 ----
  ***************
  *** 464,471 ****
    	fb->inptr = fb->inbase;
    	fb->incnt = 0;
    	if (fb->flags & B_EOF) return 0;
  ! 	do i = read(fb->fd_in, fb->inptr, fb->bufsiz);
  ! 	while (i == -1 && errno == EINTR);
    	if (i == 0) fb->flags |= B_EOF;
    	if (i == -1 && errno != EAGAIN) doerror(fb, B_RD);
    	if (i == 0 || i == -1) return i;
  --- 473,479 ----
    	fb->inptr = fb->inbase;
    	fb->incnt = 0;
    	if (fb->flags & B_EOF) return 0;
  ! 	i = saferead( fb, fb->inptr, fb->bufsiz );
    	if (i == 0) fb->flags |= B_EOF;
    	if (i == -1 && errno != EAGAIN) doerror(fb, B_RD);
    	if (i == 0 || i == -1) return i;
  
  
  
  1.115     +0 -5      apache/src/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_main.c,v
  retrieving revision 1.114
  retrieving revision 1.115
  diff -C3 -r1.114 -r1.115
  *** http_main.c	1997/01/26 21:11:53	1.114
  --- http_main.c	1997/01/30 02:42:58	1.115
  ***************
  *** 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);
  --- 1675,1680 ----
  ***************
  *** 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);
  --- 2149,2154 ----
  
  
  
  1.95      +16 -1     apache/src/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_protocol.c,v
  retrieving revision 1.94
  retrieving revision 1.95
  diff -C3 -r1.94 -r1.95
  *** http_protocol.c	1997/01/30 02:27:07	1.94
  --- http_protocol.c	1997/01/30 02:42:58	1.95
  ***************
  *** 520,530 ****
        
        /* Read past empty lines until we get a real request line,
         * a read error, the connection closes (EOF), or we timeout.
         */
        while ((len = getline(l, HUGE_STRING_LEN, conn->client, 0)) <= 0) {
  !         if ((len < 0) || bgetflag(conn->client, B_EOF))
                return 0;
        }
        if (len == (HUGE_STRING_LEN - 1))
            return 0;               /* Should be a 414 error status instead */
    
  --- 520,545 ----
        
        /* Read past empty lines until we get a real request line,
         * a read error, the connection closes (EOF), or we timeout.
  +      *
  +      * We skip empty lines because browsers have to tack a CRLF on to the end
  +      * of POSTs to support old CERN webservers.  But note that we may not
  +      * have flushed any previous response completely to the client yet.
  +      * We delay the flush as long as possible so that we can improve
  +      * performance for clients that are pipelining requests.  If a request
  +      * is pipelined then we won't block during the (implicit) read() below.
  +      * If the requests aren't pipelined, then the client is still waiting
  +      * for the final buffer flush from us, and we will block in the implicit
  +      * read().  B_SAFEREAD ensures that the BUFF layer flushes if it will
  +      * have to block during a read.
         */
  +     bsetflag( conn->client, B_SAFEREAD, 1 );
        while ((len = getline(l, HUGE_STRING_LEN, conn->client, 0)) <= 0) {
  !         if ((len < 0) || bgetflag(conn->client, B_EOF)) {
  ! 	    bsetflag( conn->client, B_SAFEREAD, 0 );
                return 0;
  + 	}
        }
  +     bsetflag( conn->client, B_SAFEREAD, 0 );
        if (len == (HUGE_STRING_LEN - 1))
            return 0;               /* Should be a 414 error status instead */
    
  
  
  

Mime
View raw message