Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 4fa5e5b
Showing
6 changed files
with
359 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# requires clang-format >= 3.6 | ||
BasedOnStyle: "LLVM" | ||
IndentWidth: 2 | ||
ColumnLimit: 120 | ||
BreakBeforeBraces: Linux | ||
AllowShortFunctionsOnASingleLine: None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
mod_vhost_maxclients.la | ||
mod_vhost_maxclients.lo | ||
mod_vhost_maxclients.o | ||
mod_vhost_maxclients.slo | ||
.libs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
language: c | ||
compiler: | ||
- gcc | ||
- clang | ||
before_install: | ||
- sudo apt-get -qq update | ||
install: | ||
- sudo apt-get -qq install rake bison libcurl4-openssl-dev libhiredis-dev libmarkdown2-dev libapr1-dev libaprutil1-dev apache2 libcap-dev | ||
env: | ||
- HTTPD_VERSION=httpd-2.2.31 | ||
APR=apr-1.5.2 | ||
APR_UTIL=apr-util-1.5.4 | ||
HTTPD_TAR=${HTTPD_VERSION}.tar.gz | ||
APR_TAR=${APR}.tar.gz | ||
APR_UTIL_TAR=${APR_UTIL}.tar.gz | ||
HTTPD_CONFIG_OPT="--enable-module=all --enable-mods-shared=all" | ||
APXS_CHECK_CMD="../${HTTPD_VERSION}/apache/bin/apachectl -v" | ||
- HTTPD_VERSION=httpd-2.4.16 | ||
APR=apr-1.5.2 | ||
APR_UTIL=apr-util-1.5.4 | ||
HTTPD_TAR=${HTTPD_VERSION}.tar.gz | ||
APR_TAR=${APR}.tar.gz | ||
APR_UTIL_TAR=${APR_UTIL}.tar.gz | ||
HTTPD_CONFIG_OPT= | ||
APXS_CHECK_CMD="../${HTTPD_VERSION}/apache/bin/apachectl -v" | ||
before_script: | ||
- cd ../ | ||
- wget http://ftp.jaist.ac.jp/pub/apache//httpd/${HTTPD_TAR} | ||
- tar xf ${HTTPD_TAR} | ||
- cd ${HTTPD_VERSION}/srclib | ||
- wget http://ftp.jaist.ac.jp/pub/apache//apr/${APR_TAR} | ||
- wget http://ftp.jaist.ac.jp/pub/apache//apr/${APR_UTIL_TAR} | ||
- tar xf ${APR_TAR} | ||
- tar xf ${APR_UTIL_TAR} | ||
- ln -s ${APR} apr | ||
- ln -s ${APR_UTIL} apr-util | ||
- cd .. | ||
- ./configure --prefix=`pwd`/apache --with-included-apr ${HTTPD_CONFIG_OPT} | ||
- make | ||
- make install | ||
- cd ../mod_vhost_maxclients | ||
script: | ||
- echo ${APXS_CHECK_CMD} | ||
- ${APXS_CHECK_CMD} | ||
- make APXS=../${HTTPD_VERSION}/apache/bin/apxs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
## | ||
## Makefile -- Build procedure for sample mod_vhost_maxclients Apache module | ||
## MATSUMOTO, Ryosuke | ||
## | ||
|
||
# target module source | ||
TARGET=mod_vhost_maxclients.c | ||
|
||
# the used tools | ||
APXS=apxs | ||
APACHECTL=apachectl -k | ||
|
||
# additional user defines, includes and libraries | ||
DEF= | ||
INC= | ||
LIB= | ||
WC=-Wc,-std=c99 | ||
|
||
# the default target | ||
all: mod_vhost_maxclients.so | ||
|
||
# compile the DSO file | ||
mod_vhost_maxclients.so: $(TARGET) | ||
$(APXS) -c $(DEF) $(INC) $(LIB) $(WC) $(TARGET) | ||
|
||
# install the DSO file into the Apache installation | ||
# and activate it in the Apache configuration | ||
install: all | ||
$(APXS) -i -a -n 'vhost_maxclients' .libs/mod_vhost_maxclients.so | ||
|
||
# cleanup | ||
clean: | ||
-rm -rf .libs *.o *.so *.lo *.la *.slo *.loT | ||
|
||
# reload the module by installing and restarting Apache | ||
reload: install restart | ||
|
||
# the general Apache start/restart/stop procedures | ||
start: | ||
$(APACHECTL) start | ||
restart: | ||
$(APACHECTL) restart | ||
stop: | ||
$(APACHECTL) stop | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# mod_vhost_maxclients | ||
|
||
MaxClients per vhost, no using shared memory and global lock. mod_vhost_maxclients use only scoreboad for simple implementation. | ||
|
||
# Quick Install | ||
- build | ||
|
||
``` | ||
make | ||
``` | ||
|
||
- mod_vhost_maxclients.conf | ||
|
||
``` | ||
LoadModule vhost_maxclients_module modules/mod_vhost_maxclients.so | ||
# mod_vhost_maxclinets use scoreboard | ||
ExtendedStatus On | ||
``` | ||
|
||
- vhost.conf | ||
|
||
```apache | ||
<VirtualHost *> | ||
DocumentRoot /path/to/web | ||
ServerName test001.example.jp | ||
# MaxClients per vhost using mod_vhost_maxclients | ||
VhostMaxClients 3 | ||
# Ignore extensions from VhostMaxClients | ||
IgnoreVhostMaxClientsExt .html .js .css | ||
</VirtualHost> | ||
``` | ||
|
||
- logggin | ||
``` | ||
[Thu Aug 27 21:16:54.540685 2015] [vhost_maxclients:debug] [pid 23981] mod_vhost_maxclients.c(93): DEBUG: (increment test001.example.jp:80): 1/3 | ||
[Thu Aug 27 21:16:54.540708 2015] [vhost_maxclients:debug] [pid 23981] mod_vhost_maxclients.c(93): DEBUG: (increment test001.example.jp:80): 2/3 | ||
[Thu Aug 27 21:16:54.540713 2015] [vhost_maxclients:debug] [pid 23981] mod_vhost_maxclients.c(93): DEBUG: (increment test001.example.jp:80): 3/3 | ||
[Thu Aug 27 21:16:54.540716 2015] [vhost_maxclients:debug] [pid 23981] mod_vhost_maxclients.c(93): DEBUG: (increment test001.example.jp:80): 4/3 | ||
[Thu Aug 27 21:16:54.540726 2015] [vhost_maxclients:notice] [pid 23981] NOTICE: (return 503 from test001.example.jp:80): 4/3 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
#include "httpd.h" | ||
#include "http_config.h" | ||
#include "http_request.h" | ||
#include "http_protocol.h" | ||
#include "http_core.h" | ||
#include "http_log.h" | ||
#include "ap_mpm.h" | ||
#include "apr_strings.h" | ||
|
||
#define MODULE_NAME "mod_vhost_maxclients" | ||
#define MODULE_VERSION "0.0.1" | ||
|
||
#if (AP_SERVER_MINORVERSION_NUMBER > 2) | ||
#define __APACHE24__ | ||
#endif | ||
|
||
#ifdef __APACHE24__ | ||
#define ap_get_scoreboard_worker ap_get_scoreboard_worker_from_indexes | ||
#endif | ||
|
||
#define _log_debug \ | ||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, "DEBUG: " MODULE_NAME "/" MODULE_VERSION "%s:%d", __func__, __LINE__) | ||
|
||
#ifdef __APACHE24__ | ||
#include "http_main.h" | ||
#else | ||
#define ap_server_conf NULL | ||
#endif | ||
|
||
#define VHOST_MAXEXTENSIONS 16 | ||
|
||
#if !defined(__APACHE24__) && defined(_WIN32) | ||
/* | ||
* libhttpd.dll does not export following variables. | ||
* This won't work correctly, but working well for other functional. | ||
*/ | ||
int ap_extended_status = 0; | ||
#endif | ||
|
||
module AP_MODULE_DECLARE_DATA vhost_maxclients_module; | ||
static int vhost_maxclients_server_limit, vhost_maxclients_thread_limit; | ||
|
||
typedef struct { | ||
|
||
/* vhost max clinetns */ | ||
signed int vhost_maxclients; | ||
apr_array_header_t *ignore_extensions; | ||
|
||
} vhost_maxclients_config; | ||
|
||
static void *vhost_maxclients_create_server_config(apr_pool_t *p, server_rec *s) | ||
{ | ||
vhost_maxclients_config *scfg = (vhost_maxclients_config *)apr_pcalloc(p, sizeof(*scfg)); | ||
|
||
scfg->vhost_maxclients = 0; | ||
scfg->ignore_extensions = apr_array_make(p, VHOST_MAXEXTENSIONS, sizeof(char *)); | ||
|
||
return scfg; | ||
} | ||
|
||
static int check_extension(char *filename, apr_array_header_t *exts) | ||
{ | ||
int i; | ||
for (i = 0; i < exts->nelts; i++) { | ||
const char *extension = ((char **)exts->elts)[i]; | ||
ssize_t name_len = strlen(filename) - strlen(extension); | ||
if (name_len >= 0 && strcmp(&filename[name_len], extension) == 0) | ||
return 1; | ||
} | ||
return 0; | ||
} | ||
|
||
static char *build_vhostport_name(request_rec *r) | ||
{ | ||
ssize_t vhostport_len; | ||
char *vhostport; | ||
|
||
vhostport_len = strlen(r->hostname) + sizeof(":65536"); | ||
vhostport = apr_pcalloc(r->pool, vhostport_len); | ||
apr_snprintf(vhostport, vhostport_len, "%s:%d", r->hostname, r->connection->local_addr->port); | ||
|
||
return vhostport; | ||
} | ||
|
||
static int vhost_maxclients_handler(request_rec *r) | ||
{ | ||
int i, j; | ||
int vhost_count = 0; | ||
char *vhostport; | ||
vhost_maxclients_config *scfg = | ||
(vhost_maxclients_config *)ap_get_module_config(r->server->module_config, &vhost_maxclients_module); | ||
|
||
if (!ap_is_initial_req(r)) { | ||
return DECLINED; | ||
} | ||
|
||
if (scfg->vhost_maxclients <= 0) { | ||
return DECLINED; | ||
} | ||
|
||
if (r->hostname == NULL) { | ||
return DECLINED; | ||
} | ||
|
||
if (!ap_extended_status) { | ||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "DEBUG: only used when ExtendedStatus On"); | ||
return DECLINED; | ||
} | ||
|
||
/* check ignore extesions */ | ||
if (check_extension(r->filename, scfg->ignore_extensions)) { | ||
return DECLINED; | ||
} | ||
|
||
/* build vhostport name */ | ||
vhostport = build_vhostport_name(r); | ||
|
||
for (i = 0; i < vhost_maxclients_server_limit; ++i) { | ||
for (j = 0; j < vhost_maxclients_thread_limit; ++j) { | ||
worker_score *ws_record = ap_get_scoreboard_worker(i, j); | ||
|
||
switch (ws_record->status) { | ||
case SERVER_BUSY_READ: | ||
case SERVER_BUSY_WRITE: | ||
case SERVER_BUSY_KEEPALIVE: | ||
case SERVER_BUSY_LOG: | ||
case SERVER_BUSY_DNS: | ||
case SERVER_CLOSING: | ||
case SERVER_GRACEFUL: | ||
if (strcmp(vhostport, ws_record->vhost) == 0) { | ||
vhost_count++; | ||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "DEBUG: (increment %s): %d/%d", vhostport, | ||
vhost_count, scfg->vhost_maxclients); | ||
if (vhost_count > scfg->vhost_maxclients) { | ||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "NOTICE: (return 503 from %s): %d/%d", vhostport, | ||
vhost_count, scfg->vhost_maxclients); | ||
return HTTP_SERVICE_UNAVAILABLE; | ||
} | ||
break; | ||
} | ||
default: | ||
break; | ||
} | ||
} | ||
} | ||
|
||
/* not reached vhost_maxclients */ | ||
return DECLINED; | ||
} | ||
|
||
static const char *set_vhost_maxclientsvhost(cmd_parms *parms, void *mconfig, const char *arg1) | ||
{ | ||
vhost_maxclients_config *scfg = | ||
(vhost_maxclients_config *)ap_get_module_config(parms->server->module_config, &vhost_maxclients_module); | ||
signed long int limit = strtol(arg1, (char **)NULL, 10); | ||
|
||
if ((limit > 65535) || (limit < 0)) { | ||
return "Integer overflow or invalid number"; | ||
} | ||
|
||
scfg->vhost_maxclients = limit; | ||
|
||
return NULL; | ||
} | ||
|
||
static const char *set_vhost_ignore_extensions(cmd_parms *parms, void *mconfig, const char *arg) | ||
{ | ||
vhost_maxclients_config *scfg = | ||
(vhost_maxclients_config *)ap_get_module_config(parms->server->module_config, &vhost_maxclients_module); | ||
|
||
if (VHOST_MAXEXTENSIONS < scfg->ignore_extensions->nelts) { | ||
return "the number of ignore extensions exceeded"; | ||
} | ||
|
||
*(const char **)apr_array_push(scfg->ignore_extensions) = arg; | ||
|
||
return NULL; | ||
} | ||
|
||
static command_rec vhost_maxclients_cmds[] = { | ||
AP_INIT_TAKE1("VhostMaxClients", set_vhost_maxclientsvhost, NULL, RSRC_CONF | ACCESS_CONF, | ||
"maximum connections per Vhost"), | ||
AP_INIT_ITERATE("IgnoreVhostMaxClientsExt", set_vhost_ignore_extensions, NULL, ACCESS_CONF | RSRC_CONF, | ||
"Set Ignore Extensions."), | ||
{NULL}, | ||
}; | ||
|
||
static int vhost_maxclients_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) | ||
{ | ||
ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &vhost_maxclients_thread_limit); | ||
ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &vhost_maxclients_server_limit); | ||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, | ||
MODULE_NAME "/" MODULE_VERSION " enabled: %d/%d thread_limit/server_limit", | ||
vhost_maxclients_thread_limit, vhost_maxclients_server_limit); | ||
|
||
return OK; | ||
} | ||
|
||
static void vhost_maxclients_register_hooks(apr_pool_t *p) | ||
{ | ||
ap_hook_post_config(vhost_maxclients_init, NULL, NULL, APR_HOOK_MIDDLE); | ||
ap_hook_access_checker(vhost_maxclients_handler, NULL, NULL, APR_HOOK_MIDDLE); | ||
} | ||
|
||
#ifdef __APACHE24__ | ||
AP_DECLARE_MODULE(vhost_maxclients) = { | ||
#else | ||
module AP_MODULE_DECLARE_DATA vhost_maxclients_module = { | ||
#endif | ||
STANDARD20_MODULE_STUFF, NULL, /* create per-dir config structures */ | ||
NULL, /* merge per-dir config structures */ | ||
vhost_maxclients_create_server_config, /* create per-server config | ||
structures */ | ||
NULL, /* merge per-server config structures */ | ||
vhost_maxclients_cmds, /* table of config file commands */ | ||
vhost_maxclients_register_hooks}; |