[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#284115: apache-common: mod_bandwidth breaks resumes/multiple downloads



On Sun, Feb 06, 2005 at 12:57:09PM +0100, Piotr Krukowiecki wrote:
> Fix: e.g. use attached file instead of 504_mod_bandwidth_paths
> (it changes MASTER_DIR and LINK_DIR so you may want to change to retain 
> backward compability)

Of course forgot to attache the file.


-- 
Piotrek
irc: #debian.pl
Mors Drosophilis melanogastribus!
--- build-tree/apache-contrib-1.0.8a/mod_bandwidth/mod_bandwidth.c	1999-08-20 09:59:02.000000000 +0200
+++ build-tree/apache-contrib-1.0.8a/mod_bandwidth/mod_bandwidth.c.mine	2004-12-06 21:16:11.000000000 +0100
@@ -54,8 +54,8 @@
  * Title       : Bandwidth management
  * File        : mod_bandwidth.c
  * Author      : Yann Stettler (stettler@cohprog.com)
- * Date        : 17 July 1999
- * Version     : 2.0 for Apache 1.3+
+ * Date        : 12 January 2003
+ * Version     : 2.0.6 for Apache 1.3+
  *
  * Description :
  *   Provide bandwidth usage limitation either on the whole server or
@@ -71,10 +71,17 @@
  *                          
  *                          Allow the use of the network/mask format when
  *                          setting a bandwidth for a remote host/network.
- *                          (Thanks to Sami Kuhmonen for the patch)                          
+ *                          (Thanks to Sami Kuhmonen for the patch) 
  *
  *                          New directive BandWidthPulse
  *
+ *               10/14/00 - Minor bug fixed
+ *               12/15/00 - Bug fix when using mmap
+ *               08/29/01 - Add a directive to change the data directory
+ *                          (Thanks to Awesome Walrus <walrus@amur.ru> )
+ *               01/12/03 - Add MaxConnection directive to limit the number
+ *                          of simultaneous connections.
+ *
  ***************************************************************************
  * Copyright (c)1997 Yann Stettler and CohProg SaRL. All rights reserved.
  * Written for the Apache Group by :
@@ -97,27 +104,53 @@
  * Instruction :
  * -------------
  *
- * Note : this module was writen for Apache 1.2b7 and tested on it
+ * Note : this module was writen for Apache 1.3.x and tested on it
  *
  * Installation :
  *
  * 1) Insert the following line at the end of the "Configuration" file :
  *    Module bandwidth_module      mod_bandwidth.o
  *
+ * WARNING : This behaviour is not the same between the various main versions
+ *           of Apache. Please, read the instruction on our website for the
+ *           instructions concerning the latest release : 
+ *           http://www.cohprog.com/v3/bandwidth/doc-en.html
+ *
  * 2) Run the "Configure" program and re-compile the server with "make".
  *
  * 3) Create the following directories with "rwx" permission to everybody :
+ *    (or rwx for the user under which Apache run : Usualy "nobody")
  *    /tmp/apachebw
  *    /tmp/apachebw/link
  *    /tmp/apachebw/master
  *
+ *  /==== by Awesome Walrus <walrus@amur.ru> =====================\
+ *    Or you may change this name by using BandWidthDataDir global
+ *    configuration directive. See below for details.
+ *  \==== by Awesome Walrus <walrus@amur.ru> =====================/
+ *
  * Note that if any of those directories doesn't exist, or if they can't
  * be accessed by the server, the module is totaly disabled except for
  * logging an error message in the logfile.
  *
+ * Be careful that on some systems the content of the /tmp directory
+ * is deleted at boot time or every so often by a cronjob. If that the
+ * case, either disable this feature or change the location of the
+ * directories used by the module in the sources bellow.
+ *
  * Server configuration directive :
  * --------------------------------
  *
+ *  /==== by Awesome Walrus <walrus@amur.ru> =====================\
+ * -  BandWidthDataDir
+ *    Syntax  : BandWidthDataDir <directory>
+ *    Default : "/tmp/apachebw"
+ *    Context : server config
+ *
+ *    Sets the name of the directory used by mod_bandwidth to store
+ *    its internal temporary information.
+ *  \==== by Awesome Walrus <walrus@amur.ru> =====================/
+ *
  * -  BandWidthModule 
  *    Syntax  : BandWidthModule <On|Off>
  *    Default : Off
@@ -250,7 +283,7 @@
  *    <rate> is in bytes per second.
  *
  *    A rate of "0" explicitly means to use the default minimal
- *    value (256 KBytes/sec).
+ *    value (256 Bytes/sec).
  *
  *    A rate of "-1" means that the minimal rate is equal to the
  *    actual rate defined by BandWidth and LargeFileLimit.
@@ -291,6 +324,16 @@
  *        basis. (Ie: each virtual server will have that limit,
  *        _independantly_ of the other servers)
  *
+ * -  MaxConnection
+ *    Syntax  : MaxConnection <connections>
+ *    Default : 0 (illimited)
+ *    Context : per directory, .htaccess 
+ *
+ *    Restrict the number of maximum simultanous connections. If the
+ *    limit is reached, new connections will be rejected.
+ "
+ *    A value of 0 mean that there isn't any limits.
+ *
  * Implementation notes :
  * ----------------------
  * 
@@ -314,7 +357,7 @@
  *    no faster than the limited rate :) ...
  *
  * 4) Some kind of buffering is done as side effect. Data are
- *    sent in packet of 1024 KBytes which seems a good value
+ *    sent in packet of 1024 Bytes which seems a good value
  *    for TCP/IP.
  *    If another packet size is wanted, change the value of
  *    "#define PACKET" in the codes bellow.
@@ -340,22 +383,26 @@
 #define MIN_BW_DEFAULT  256        /* Minimal bandwidth defaulted to 256Bps */
 #define PACKET 1024                /* Sent packet of 1024 bytes             */
 
-#define MASTER_DIR  "/tmp/apachebw/master"
-#define LINK_DIR    "/tmp/apachebw/link"
+/* #define MASTER_DIR  "/tmp/apachebw/master"
+ * #define LINK_DIR    "/tmp/apachebw/link"
+ */
 
-#ifdef USE_MMAP_FILES
-#include <unistd.h>
-#include <sys/mman.h>
+#define MASTER_DIR  "master"
+#define LINK_DIR    "link"
 
 /* Define BWDEBUG for debuging purpose only ! */
 /* #define BWDEBUG */
 #ifdef BWDEBUG
 #undef BWDEBUG
-#endif 
+#endif
 
 #define BANDWIDTH_DISABLED             1<<0
 #define BANDWIDTH_ENABLED              1<<1
 
+#ifdef USE_MMAP_FILES
+#include <unistd.h>
+#include <sys/mman.h>
+
 /* mmap support for static files based on ideas from John Heidemann's
  * patch against 1.0.5.  See
  * <http://www.isi.edu/~johnh/SOFTWARE/APACHE/index.html>.
@@ -391,6 +438,7 @@ typedef struct {
   array_header *limits;
   array_header *minlimits;
   array_header *sizelimits;
+  int maxconnection;
   char  *directory;
 } bandwidth_config;
 
@@ -405,6 +453,8 @@ module bandwidth_module;
 
 static long int BWPulse=0;
 
+char bandwidth_data_dir[MAX_STRING_LEN]="/var/lib/apache/mod-bandwidth";
+
 /***************************************************************************
  * Configuration functions                                                 *
  ***************************************************************************/
@@ -416,6 +466,7 @@ static void *create_bw_config(pool *p, c
   new->minlimits=ap_make_array(p,20,sizeof(bw_entry));
   new->sizelimits=ap_make_array(p,10,sizeof(bw_sizel));
   new->directory=ap_pstrdup(p, path);
+  new->maxconnection=0;
   return (void *)new; 
 }
 
@@ -442,6 +493,16 @@ static const char *bandwidthmodule(cmd_p
    return NULL;
 }
 
+static const char *set_bandwidth_data_dir(cmd_parms *cmd, void *dummy, char *arg) {
+    arg = ap_os_canonical_filename(cmd->pool, arg);
+
+    if (!ap_is_directory(arg)) {
+        return "BandWidthDataDir must be a valid directory";
+    }
+    ap_cpystrn(bandwidth_data_dir, arg, sizeof(bandwidth_data_dir));
+    return NULL;
+}
+
 static const char *setpulse(cmd_parms *cmd, bandwidth_config *dconf, char *pulse) {
    long int temp;
 
@@ -451,13 +512,30 @@ static const char *setpulse(cmd_parms *c
      return "Invalid argument";
 
    if (temp<0)
-     return "BandWidth must be a number of bytes/s";
+     return "Pulse must be a number of microseconds/s";
 
    BWPulse=temp;
 
    return NULL;
 }
 
+static const char *MaxConnection(cmd_parms *cmd, void *s, char *maxc) { 
+   bandwidth_config *conf=(bandwidth_config *)s;
+   int temp;
+ 
+   if (maxc && *maxc && isdigit(*maxc))
+     temp = atoi(maxc); 
+   else 
+     return "Invalid argument";
+ 
+   if (temp<0)
+     return "Connections must be a number of simultaneous connections allowed/s";
+ 
+   conf->maxconnection=temp;
+ 
+   return NULL;
+} 
+
 static const char *bandwidth(cmd_parms *cmd, void *s, char *from, char *bw) {
   bandwidth_config *conf=(bandwidth_config *)s;
   bw_entry *a;
@@ -529,10 +607,14 @@ static command_rec bw_cmds[] = {
     "a domain (or ip, or all for all) and a minimal bandwidth limit (in bytes/s)" },
 { "LargeFileLimit", largefilelimit, NULL, RSRC_CONF | OR_LIMIT, TAKE2,
     "a filesize (in Kbytes) and a bandwidth limit (in bytes/s)" },
+{ "MaxConnection", MaxConnection, NULL, RSRC_CONF | OR_LIMIT, TAKE1,
+    "A number of allowed simultaneous connections" },
 { "BandWidthModule",   bandwidthmodule,  NULL, OR_FILEINFO, FLAG, 
       "On or Off to enable or disable (default) the whole bandwidth module" },
 { "BandWidthPulse", setpulse, NULL, OR_FILEINFO, TAKE1,
     "a number of microseconds" },
+{ "BandWidthDataDir", set_bandwidth_data_dir, NULL, RSRC_CONF, TAKE1,
+    "A writable directory where temporary bandwidth info is to be stored" },
 { NULL }
 };
 
@@ -578,7 +660,7 @@ static int in_ip(char *domain, char *wha
      * "allow from 204.26.2" shouldn't let in people from 204.26.23
      */
     int a, b, c, d, e; 
-    unsigned long in, out, inmask;
+    unsigned long in, out, inmask, outmask;
 
     if (sscanf(domain, "%i.%i.%i.%i/%i", &a, &b, &c, &d, &e) < 5) {
        int l = strlen(domain);
@@ -693,7 +775,7 @@ static int handle_bw(request_rec *r) {
   bandwidth_server_config *sconf =
      (bandwidth_server_config *)ap_get_module_config(r->server->module_config, &bandwidth_module);
   long int bw_rate=0, bw_min=0, bw_f_rate=0, cur_rate;
-  int bwlast=0, fd;
+  int nolimit=0, bwlast=0, fd;
   long int tosend, bytessent, filelength;
   struct stat fdata;
   struct timeval opt_time, last_time, now, timespent, timeout;
@@ -724,7 +806,15 @@ static int handle_bw(request_rec *r) {
   bw_min=get_bw_rate(r, conf->minlimits);
   bw_f_rate=get_bw_filesize(r, conf->sizelimits , r->finfo.st_size);
 
-  if ((bw_rate==0 && bw_f_rate==0) || bw_f_rate < 0 || !directory) return DECLINED;
+  if (!directory) return DECLINED;
+
+  if ((bw_rate==0 && bw_f_rate==0) || bw_f_rate < 0) {
+     if (!conf->maxconnection) {
+         return DECLINED;
+     } else {
+         nolimit=1;
+     }
+  }
 
   if (r->finfo.st_mode == 0 || (r->path_info && *r->path_info)) {
       ap_log_reason("File does not exist", r->filename, r);
@@ -745,11 +835,11 @@ static int handle_bw(request_rec *r) {
    * directory.
    */
 
-  if (stat(directory, &fdata) < -1) {
+  if (stat(directory, &fdata) < 0) {
      /* Dunno if this may happen... but well... */
      return DECLINED;
   }
-  sprintf(masterfile,"%s/%d:%ld",  MASTER_DIR, (short int)fdata.st_dev, (long int)fdata.st_ino);
+  sprintf(masterfile,"%s/%s/%d:%ld",  bandwidth_data_dir, MASTER_DIR, (short int)fdata.st_dev, (long int)fdata.st_ino);
 
   /*
    * Check if master file already exist, else create it.
@@ -761,7 +851,15 @@ static int handle_bw(request_rec *r) {
   }
   close(fd);
 
-  sprintf(filelink,"%s/%d", LINK_DIR, getpid());
+  /*
+   * Check if the maximum number of connections allowed is reached
+   */
+  if (conf->maxconnection && (conf->maxconnection <= current_connection(masterfile))) {
+/*     return HTTP_SERVICE_UNAVAILABLE; */
+       return FORBIDDEN;
+  }
+
+  sprintf(filelink,"%s/%s/%d", bandwidth_data_dir, LINK_DIR, getpid());
   if (link(masterfile, filelink) < 0) {
      ap_log_printf(r->server, "mod_bandwidth : Can't create hard link %s", filelink);
      return DECLINED;
@@ -772,6 +870,7 @@ static int handle_bw(request_rec *r) {
   if (f == NULL) {
      ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
                 "file permissions deny server access: %s", r->filename);
+     unlink(filelink); 
      return FORBIDDEN;
   }
 
@@ -815,7 +914,7 @@ static int handle_bw(request_rec *r) {
   if (mm == (caddr_t)-1) {
       ap_unblock_alarms();
 
-      if (r->finfo.st_size >= MMAP_THRESHOLD) {
+      if ((r->finfo.st_size >= MMAP_THRESHOLD) && (!r->header_only)) {
           ap_log_error(APLOG_MARK, APLOG_CRIT, r->server,
                       "mmap_handler: mmap failed: %s", r->filename);
       }
@@ -846,9 +945,13 @@ static int handle_bw(request_rec *r) {
                  * this case, I feel that I have the moral right to do so :)
                  */
 
-                opt_time.tv_sec=(long int) PACKET / cur_rate;
-                opt_time.tv_usec=(long int)PACKET*1000000/cur_rate-opt_time.tv_sec*1000000;
-
+                if (nolimit) {
+                   opt_time.tv_sec=0;
+                   opt_time.tv_usec=0;
+                } else {
+                   opt_time.tv_sec=(long int) PACKET / cur_rate;
+                   opt_time.tv_usec=(long int)PACKET*1000000/cur_rate-opt_time.tv_sec*1000000;
+                }
                 tosend=PACKET;
                 if (tosend+bytessent >= filelength) {
                    tosend=filelength-bytessent;
@@ -858,7 +961,10 @@ static int handle_bw(request_rec *r) {
                 opt_time.tv_sec=(long int)BWPulse/1000000;
                 opt_time.tv_usec=BWPulse-opt_time.tv_sec*1000000;
 
-                tosend=(long int)((double)BWPulse/(double)1000000*(double)cur_rate);
+                if (nolimit)
+                   tosend=filelength;
+                else
+                   tosend=(long int)((double)BWPulse/(double)1000000*(double)cur_rate);
                 if (tosend+bytessent >= filelength) {
                    tosend=filelength-bytessent;
                    bwlast=1;
@@ -905,8 +1011,13 @@ static int handle_bw(request_rec *r) {
                     cur_rate=bw_min;
 
                  if (BWPulse <= 0) {
-                    opt_time.tv_sec=(long int) PACKET / cur_rate;
-                    opt_time.tv_usec=(long int)PACKET*1000000/cur_rate-opt_time.tv_sec*1000000;
+                    if (nolimit) {
+                      opt_time.tv_sec=0;
+                      opt_time.tv_usec=0;
+                    } else {
+                      opt_time.tv_sec=(long int) PACKET / cur_rate;
+                      opt_time.tv_usec=(long int)PACKET*1000000/cur_rate-opt_time.tv_sec*1000000;
+                    }
 
                     tosend=PACKET;
                     if (tosend+bytessent >= filelength) {
@@ -916,8 +1027,11 @@ static int handle_bw(request_rec *r) {
                  } else {
                     opt_time.tv_sec=(long int)BWPulse/1000000;
                     opt_time.tv_usec=BWPulse-opt_time.tv_sec*1000000;
-  
-                    tosend=(long int)((double)BWPulse/(double)1000000*(double)cur_rate);
+ 
+                    if (nolimit)
+                       tosend=filelength;
+                    else 
+                       tosend=(long int)((double)BWPulse/(double)1000000*(double)cur_rate);
                     if (tosend+bytessent >= filelength) {
                        tosend=filelength-bytessent;
                        bwlast=1;
@@ -987,8 +1101,13 @@ static int handle_bw(request_rec *r) {
                     * this case, I feel that I have the moral right to do so :)
                     */
 
-                   opt_time.tv_sec=(long int) PACKET / cur_rate;
-                   opt_time.tv_usec=(long int)PACKET*1000000/cur_rate-opt_time.tv_sec*1000000;
+                   if (nolimit) {
+                      opt_time.tv_sec=0;
+                      opt_time.tv_usec=0;
+                   } else {
+                      opt_time.tv_sec=(long int) PACKET / cur_rate;
+                      opt_time.tv_usec=(long int)PACKET*1000000/cur_rate-opt_time.tv_sec*1000000;
+                   }
 
                    tosend=PACKET;
                    if (tosend+bytessent >= filelength) {
@@ -999,7 +1118,10 @@ static int handle_bw(request_rec *r) {
                    opt_time.tv_sec=(long int)BWPulse/1000000;
                    opt_time.tv_usec=BWPulse-opt_time.tv_sec*1000000;
 
-                   tosend=(long int)((double)BWPulse/(double)1000000*(double)cur_rate);
+                   if (nolimit)
+                      tosend=filelength;
+                   else
+                      tosend=(long int)((double)BWPulse/(double)1000000*(double)cur_rate);
                    if (tosend+bytessent >= filelength) {
                       tosend=filelength-bytessent;
                       bwlast=1;
@@ -1044,8 +1166,13 @@ static int handle_bw(request_rec *r) {
                       cur_rate=bw_min;
 
                    if (BWPulse <= 0) { 
-                      opt_time.tv_sec=(long int) PACKET / cur_rate;
-                      opt_time.tv_usec=(long int)PACKET*1000000/cur_rate-opt_time.tv_sec*1000000;
+                      if (nolimit) {
+                        opt_time.tv_sec=0;
+                        opt_time.tv_usec=0;
+                      } else {
+                         opt_time.tv_sec=(long int) PACKET / cur_rate;
+                         opt_time.tv_usec=(long int)PACKET*1000000/cur_rate-opt_time.tv_sec*1000000;
+                      }
    
                       tosend=PACKET;
                       if (tosend+bytessent >= filelength) {
@@ -1056,7 +1183,10 @@ static int handle_bw(request_rec *r) {
                       opt_time.tv_sec=(long int)BWPulse/1000000;
                       opt_time.tv_usec=BWPulse-opt_time.tv_sec*1000000;
 
-                      tosend=(long int)((double)BWPulse/(double)1000000*(double)cur_rate);
+                      if (nolimit)
+                         tosend=filelength;
+                      else
+                         tosend=(long int)((double)BWPulse/(double)1000000*(double)cur_rate);
                       if (tosend+bytessent >= filelength) {
                          tosend=filelength-bytessent;
                          bwlast=1;
@@ -1069,7 +1199,7 @@ static int handle_bw(request_rec *r) {
 #endif 
                    gettimeofday(&last_time, (struct timezone *) 0);
    
-                   ap_send_mmap(mm, r, offset, tosend);
+                   ap_send_mmap(mm, r, offset+bytessent, tosend);
                    bytessent += tosend;
                    if (r->connection->aborted)
                       break;

Reply to: