You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by mi...@apache.org on 2002/03/09 08:15:33 UTC

cvs commit: httpd-2.0/modules/proxy mod_proxy.c mod_proxy.h proxy_ftp.c proxy_http.c

minfrin     02/03/08 23:15:33

  Modified:    .        CHANGES
               modules/proxy mod_proxy.c mod_proxy.h proxy_ftp.c
                        proxy_http.c
  Log:
  New directive ProxyIOBufferSize. Sets the size of the buffer used
  when reading from a remote HTTP server in proxy.
  
  Modify receive/send loop in proxy_http and proxy_ftp so that
  should it be necessary, the remote server socket is closed before
  transmitting the last buffer (set by ProxyIOBufferSize) to the
  client. This prevents the backend server from being forced to hang
  around while the last few bytes are transmitted to a slow client.
  Fix the case where no error checking was performed on the final
  brigade in the loop.
  
  Revision  Changes    Path
  1.626     +11 -0     httpd-2.0/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/CHANGES,v
  retrieving revision 1.625
  retrieving revision 1.626
  diff -u -r1.625 -r1.626
  --- CHANGES	9 Mar 2002 06:59:27 -0000	1.625
  +++ CHANGES	9 Mar 2002 07:15:33 -0000	1.626
  @@ -1,5 +1,16 @@
   Changes with Apache 2.0.34-dev
   
  +  *) New directive ProxyIOBufferSize. Sets the size of the buffer used
  +     when reading from a remote HTTP server in proxy. [Graham Leggett]
  +
  +  *) Modify receive/send loop in proxy_http and proxy_ftp so that
  +     should it be necessary, the remote server socket is closed before
  +     transmitting the last buffer (set by ProxyIOBufferSize) to the
  +     client. This prevents the backend server from being forced to hang
  +     around while the last few bytes are transmitted to a slow client.
  +     Fix the case where no error checking was performed on the final
  +     brigade in the loop. [Graham Leggett]
  +
     *) Scrap CacheMaxExpireMin and CacheDefaultExpireMin. Change
        CacheMaxExpire and CacheDefaultExpire to use seconds rather than
        hours. [Graham Leggett, Bill Stoddard]
  
  
  
  1.73      +17 -0     httpd-2.0/modules/proxy/mod_proxy.c
  
  Index: mod_proxy.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/proxy/mod_proxy.c,v
  retrieving revision 1.72
  retrieving revision 1.73
  diff -u -r1.72 -r1.73
  --- mod_proxy.c	27 Feb 2002 15:49:01 -0000	1.72
  +++ mod_proxy.c	9 Mar 2002 07:15:33 -0000	1.73
  @@ -489,6 +489,8 @@
       ps->req_set = 0;
       ps->recv_buffer_size = 0; /* this default was left unset for some reason */
       ps->recv_buffer_size_set = 0;
  +    ps->io_buffer_size = AP_IOBUFSIZE;
  +    ps->io_buffer_size_set = 0;
       ps->maxfwd = DEFAULT_MAX_FORWARDS;
       ps->maxfwd_set = 0;
       ps->error_override = 0; 
  @@ -518,6 +520,7 @@
       ps->viaopt = (overrides->viaopt_set == 0) ? base->viaopt : overrides->viaopt;
       ps->req = (overrides->req_set == 0) ? base->req : overrides->req;
       ps->recv_buffer_size = (overrides->recv_buffer_size_set == 0) ? base->recv_buffer_size : overrides->recv_buffer_size;
  +    ps->io_buffer_size = (overrides->io_buffer_size_set == 0) ? base->io_buffer_size : overrides->io_buffer_size;
       ps->maxfwd = (overrides->maxfwd_set == 0) ? base->maxfwd : overrides->maxfwd;
       ps->error_override = (overrides->error_override_set == 0) ? base->error_override : overrides->error_override;
       ps->preserve_host = (overrides->preserve_host_set == 0) ? base->preserve_host : overrides->preserve_host;
  @@ -842,6 +845,18 @@
   }
   
   static const char *
  +    set_io_buffer_size(cmd_parms *parms, void *dummy, const char *arg)
  +{
  +    proxy_server_conf *psf =
  +    ap_get_module_config(parms->server->module_config, &proxy_module);
  +    long s = atol(arg);
  +
  +    psf->io_buffer_size = MAX(s, AP_IOBUFSIZE);
  +    psf->io_buffer_size_set = 1;
  +    return NULL;
  +}
  +
  +static const char *
       set_max_forwards(cmd_parms *parms, void *dummy, const char *arg)
   {
       proxy_server_conf *psf =
  @@ -1004,6 +1019,8 @@
        "A list of names, hosts or domains to which the proxy will not connect"),
       AP_INIT_TAKE1("ProxyReceiveBufferSize", set_recv_buffer_size, NULL, RSRC_CONF,
        "Receive buffer size for outgoing HTTP and FTP connections in bytes"),
  +    AP_INIT_TAKE1("ProxyIOBufferSize", set_io_buffer_size, NULL, RSRC_CONF,
  +     "IO buffer size for outgoing HTTP and FTP connections in bytes"),
       AP_INIT_TAKE1("ProxyMaxForwards", set_max_forwards, NULL, RSRC_CONF,
        "The maximum number of proxies a request may be forwarded through."),
       AP_INIT_ITERATE("NoProxy", set_proxy_dirconn, NULL, RSRC_CONF,
  
  
  
  1.75      +3 -1      httpd-2.0/modules/proxy/mod_proxy.h
  
  Index: mod_proxy.h
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/proxy/mod_proxy.h,v
  retrieving revision 1.74
  retrieving revision 1.75
  diff -u -r1.74 -r1.75
  --- mod_proxy.h	8 Mar 2002 02:03:47 -0000	1.74
  +++ mod_proxy.h	9 Mar 2002 07:15:33 -0000	1.75
  @@ -175,8 +175,10 @@
         via_full
       } viaopt;                   /* how to deal with proxy Via: headers */
       char viaopt_set;
  -    size_t recv_buffer_size;
  +    apr_size_t recv_buffer_size;
       char recv_buffer_size_set;
  +    apr_size_t io_buffer_size;
  +    char io_buffer_size_set;
       long maxfwd;
       char maxfwd_set;
       /** 
  
  
  
  1.113     +60 -9     httpd-2.0/modules/proxy/proxy_ftp.c
  
  Index: proxy_ftp.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/proxy/proxy_ftp.c,v
  retrieving revision 1.112
  retrieving revision 1.113
  diff -u -r1.112 -r1.113
  --- proxy_ftp.c	7 Mar 2002 09:27:16 -0000	1.112
  +++ proxy_ftp.c	9 Mar 2002 07:15:33 -0000	1.113
  @@ -1804,28 +1804,79 @@
   
       /* send body */
       if (!r->header_only) {
  +        apr_bucket *e;
  +        int finish = FALSE;
   
           ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
                        "proxy: FTP: start body send");
   
           /* read the body, pass it to the output filters */
  -        while (ap_get_brigade(data->input_filters, bb, AP_MODE_EXHAUSTIVE,
  -                              APR_BLOCK_READ, 0) == APR_SUCCESS) {
  -            if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
  -                ap_pass_brigade(r->output_filters, bb);
  +        while (ap_get_brigade(data->input_filters, 
  +                              bb, 
  +                              AP_MODE_READBYTES, 
  +                              APR_BLOCK_READ, 
  +                              conf->io_buffer_size) == APR_SUCCESS) {
  +#if DEBUGGING
  +            {
  +                apr_off_t readbytes;
  +                apr_brigade_length(bb, 0, &readbytes);
  +                ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0,
  +                             r->server, "proxy (PID %d): readbytes: %#x",
  +                             getpid(), readbytes);
  +            }
  +#endif
  +            /* sanity check */
  +            if (APR_BRIGADE_EMPTY(bb)) {
  +                apr_brigade_cleanup(bb);
                   break;
               }
  +
  +            /* found the last brigade? */
  +            if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
  +                /* if this is the last brigade, cleanup the
  +                 * backend connection first to prevent the
  +                 * backend server from hanging around waiting
  +                 * for a slow client to eat these bytes
  +                 */
  +                ap_flush_conn(data);
  +                apr_socket_close(data_sock);
  +                data_sock = NULL;
  +                ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
  +                             "proxy: FTP: data connection closed");
  +                /* signal that we must leave */
  +                finish = TRUE;
  +            }
  +
  +            /* if no EOS yet, then we must flush */
  +            if (FALSE == finish) {
  +                e = apr_bucket_flush_create();
  +                APR_BRIGADE_INSERT_TAIL(bb, e);
  +            }
  +
  +            /* try send what we read */
               if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS) {
                   /* Ack! Phbtt! Die! User aborted! */
  -                break;
  +                finish = TRUE;
               }
  +
  +            /* make sure we always clean up after ourselves */
               apr_brigade_cleanup(bb);
  +
  +            /* if we are done, leave */
  +            if (TRUE == finish) {
  +                break;
  +            }
           }
  +        ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
  +                     "proxy: FTP: end body send");
  +
  +    }
  +    if (data_sock) {
  +        ap_flush_conn(data);
  +        apr_socket_close(data_sock);
  +        ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
  +                     "proxy: FTP: data connection closed");
       }
  -    ap_flush_conn(data);
  -    apr_socket_close(data_sock);
  -    ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
  -                 "proxy: FTP: Closing Data connection.");
   
       /* Retrieve the final response for the RETR or LIST commands */
       rc = proxy_ftp_command(NULL, r, origin, bb, &ftpmessage);
  
  
  
  1.134     +43 -11    httpd-2.0/modules/proxy/proxy_http.c
  
  Index: proxy_http.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/proxy/proxy_http.c,v
  retrieving revision 1.133
  retrieving revision 1.134
  diff -u -r1.133 -r1.134
  --- proxy_http.c	8 Mar 2002 02:03:47 -0000	1.133
  +++ proxy_http.c	9 Mar 2002 07:15:33 -0000	1.134
  @@ -75,6 +75,10 @@
       int             close;
   } proxy_http_conn_t;
   
  +static apr_status_t ap_proxy_http_cleanup(request_rec *r,
  +                                          proxy_http_conn_t *p_conn,
  +                                          proxy_conn_rec *backend);
  +
   /*
    * Canonicalise http-like URLs.
    *  scheme is the scheme for the URL
  @@ -813,17 +817,19 @@
                            "proxy: start body send");
                
               /*
  -             * if we are overriding the errors, we cant put the content of the
  -             * page into the brigade
  +             * if we are overriding the errors, we can't put the content
  +             * of the page into the brigade
                */
               if ( (conf->error_override ==0) || r->status < 400 ) {
  -            /* read the body, pass it to the output filters */
  +
  +                /* read the body, pass it to the output filters */
                   apr_bucket *e;
  +                int finish = FALSE;
                   while (ap_get_brigade(rp->input_filters, 
                                         bb, 
                                         AP_MODE_READBYTES, 
                                         APR_BLOCK_READ, 
  -                                      AP_IOBUFSIZE) == APR_SUCCESS) {
  +                                      conf->io_buffer_size) == APR_SUCCESS) {
   #if DEBUGGING
                       {
                       apr_off_t readbytes;
  @@ -833,21 +839,44 @@
                                    getpid(), readbytes);
                       }
   #endif
  +                    /* sanity check */
                       if (APR_BRIGADE_EMPTY(bb)) {
  +                        apr_brigade_cleanup(bb);
                           break;
                       }
  +
  +                    /* found the last brigade? */
                       if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
  -                        ap_pass_brigade(r->output_filters, bb);
  -                        break;
  +                        /* if this is the last brigade, cleanup the
  +                         * backend connection first to prevent the
  +                         * backend server from hanging around waiting
  +                         * for a slow client to eat these bytes
  +                         */
  +                        ap_proxy_http_cleanup(r, p_conn, backend);
  +                        /* signal that we must leave */
  +                        finish = TRUE;
                       }
  -                    e = apr_bucket_flush_create();
  -                    APR_BRIGADE_INSERT_TAIL(bb, e);
  +
  +                    /* if no EOS yet, then we must flush */
  +                    if (FALSE == finish) {
  +                        e = apr_bucket_flush_create();
  +                        APR_BRIGADE_INSERT_TAIL(bb, e);
  +                    }
  +
  +                    /* try send what we read */
                       if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS) {
                           /* Ack! Phbtt! Die! User aborted! */
                           p_conn->close = 1;  /* this causes socket close below */
  -                        break;
  +                        finish = TRUE;
                       }
  +
  +                    /* make sure we always clean up after ourselves */
                       apr_brigade_cleanup(bb);
  +
  +                    /* if we are done, leave */
  +                    if (TRUE == finish) {
  +                        break;
  +                    }
                   }
               }
               ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
  @@ -886,8 +915,11 @@
        * we close the socket, otherwise we leave it open for KeepAlive support
        */
       if (p_conn->close || (r->proto_num < HTTP_VERSION(1,1))) {
  -        apr_socket_close(p_conn->sock);
  -        backend->connection = NULL;
  +        if (p_conn->sock) {
  +            apr_socket_close(p_conn->sock);
  +            p_conn->sock = NULL;
  +            backend->connection = NULL;
  +        }
       }
       return OK;
   }