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 ([EMAIL PROTECTED]) - * 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 <[EMAIL PROTECTED]> ) + * 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 <[EMAIL PROTECTED]> =====================\ + * Or you may change this name by using BandWidthDataDir global + * configuration directive. See below for details. + * \==== by Awesome Walrus <[EMAIL PROTECTED]> =====================/ + * * 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 <[EMAIL PROTECTED]> =====================\ + * - 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 <[EMAIL PROTECTED]> =====================/ + * * - 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;