diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/nginx.c | 109 | ||||
-rw-r--r-- | src/core/ngx_cycle.c | 5 | ||||
-rw-r--r-- | src/core/ngx_cycle.h | 2 | ||||
-rw-r--r-- | src/core/ngx_module.c | 308 | ||||
-rw-r--r-- | src/core/ngx_module.h | 239 |
5 files changed, 653 insertions, 10 deletions
diff --git a/src/core/nginx.c b/src/core/nginx.c index 22441a84c..6ce030cb1 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -24,6 +24,10 @@ static char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +#if (NGX_HAVE_DLOPEN) +static void ngx_unload_module(void *data); +#endif static ngx_conf_enum_t ngx_debug_points[] = { @@ -133,6 +137,13 @@ static ngx_command_t ngx_core_commands[] = { 0, NULL }, + { ngx_string("load_module"), + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + ngx_load_module, + 0, + 0, + NULL }, + ngx_null_command }; @@ -1403,3 +1414,101 @@ ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_OK; } + + +static char * +ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ +#if (NGX_HAVE_DLOPEN) + void *handle; + char **names, **order; + ngx_str_t *value, file; + ngx_uint_t i; + ngx_module_t *module, **modules; + ngx_pool_cleanup_t *cln; + + if (cf->cycle->modules_used) { + return "is specified too late"; + } + + value = cf->args->elts; + + file = value[1]; + + if (ngx_conf_full_name(cf->cycle, &file, 0) != NGX_OK) { + return NGX_CONF_ERROR; + } + + cln = ngx_pool_cleanup_add(cf->cycle->pool, 0); + if (cln == NULL) { + return NGX_CONF_ERROR; + } + + handle = ngx_dlopen(file.data); + if (handle == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + ngx_dlopen_n " \"%s\" failed (%s)", + file.data, ngx_dlerror()); + return NGX_CONF_ERROR; + } + + cln->handler = ngx_unload_module; + cln->data = handle; + + modules = ngx_dlsym(handle, "ngx_modules"); + if (modules == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + ngx_dlsym_n " \"%V\", \"%s\" failed (%s)", + &value[1], "ngx_modules", ngx_dlerror()); + return NGX_CONF_ERROR; + } + + names = ngx_dlsym(handle, "ngx_module_names"); + if (names == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + ngx_dlsym_n " \"%V\", \"%s\" failed (%s)", + &value[1], "ngx_module_names", ngx_dlerror()); + return NGX_CONF_ERROR; + } + + order = ngx_dlsym(handle, "ngx_module_order"); + + for (i = 0; modules[i]; i++) { + module = modules[i]; + module->name = names[i]; + + if (ngx_add_module(cf, &file, module, order) != NGX_OK) { + return NGX_CONF_ERROR; + } + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0, "module: %s i:%i", + module->name, module->index); + } + + return NGX_CONF_OK; + +#else + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"load_module\" is not supported " + "on this platform"); + return NGX_CONF_ERROR; + +#endif +} + + +#if (NGX_HAVE_DLOPEN) + +static void +ngx_unload_module(void *data) +{ + void *handle = data; + + if (ngx_dlclose(handle) != 0) { + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + ngx_dlclose_n " failed (%s)", ngx_dlerror()); + } +} + +#endif diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index 946f8c008..f1032668a 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -212,7 +212,10 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len); - cycle->modules = ngx_modules; + if (ngx_cycle_modules(cycle) != NGX_OK) { + ngx_destroy_pool(pool); + return NULL; + } for (i = 0; cycle->modules[i]; i++) { diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h index 736fb65a1..27401d0b9 100644 --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -49,6 +49,8 @@ struct ngx_cycle_s { ngx_uint_t free_connection_n; ngx_module_t **modules; + ngx_uint_t modules_n; + ngx_uint_t modules_used; /* unsigned modules_used:1; */ ngx_queue_t reusable_connections_queue; diff --git a/src/core/ngx_module.c b/src/core/ngx_module.c index df3cfde5d..1e947c906 100644 --- a/src/core/ngx_module.c +++ b/src/core/ngx_module.c @@ -10,7 +10,16 @@ #include <ngx_core.h> -ngx_uint_t ngx_max_module; +#define NGX_MAX_DYNAMIC_MODULES 128 + + +static ngx_uint_t ngx_module_index(ngx_cycle_t *cycle); +static ngx_uint_t ngx_module_ctx_index(ngx_cycle_t *cycle, ngx_uint_t type, + ngx_uint_t index); + + +ngx_uint_t ngx_max_module; +static ngx_uint_t ngx_modules_n; ngx_int_t @@ -20,9 +29,36 @@ ngx_preinit_modules() ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { - ngx_modules[i]->index = ngx_max_module++; + ngx_modules[i]->index = i; + ngx_modules[i]->name = ngx_module_names[i]; } + ngx_modules_n = i; + ngx_max_module = ngx_modules_n + NGX_MAX_DYNAMIC_MODULES; + + return NGX_OK; +} + + +ngx_int_t +ngx_cycle_modules(ngx_cycle_t *cycle) +{ + /* + * create a list of modules to be used for this cycle, + * copy static modules to it + */ + + cycle->modules = ngx_pcalloc(cycle->pool, (ngx_max_module + 1) + * sizeof(ngx_module_t *)); + if (cycle->modules == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(cycle->modules, ngx_modules, + ngx_modules_n * sizeof(ngx_module_t *)); + + cycle->modules_n = ngx_modules_n; + return NGX_OK; } @@ -47,19 +83,279 @@ ngx_init_modules(ngx_cycle_t *cycle) ngx_int_t ngx_count_modules(ngx_cycle_t *cycle, ngx_uint_t type) { - ngx_uint_t i, max; + ngx_uint_t i, next, max; + ngx_module_t *module; + next = 0; max = 0; /* count appropriate modules, set up their indices */ for (i = 0; cycle->modules[i]; i++) { - if (cycle->modules[i]->type != type) { + module = cycle->modules[i]; + + if (module->type != type) { + continue; + } + + if (module->ctx_index != NGX_MODULE_UNSET_INDEX) { + + /* if ctx_index was assigned, preserve it */ + + if (module->ctx_index > max) { + max = module->ctx_index; + } + + if (module->ctx_index == next) { + next++; + } + + continue; + } + + /* search for some free index */ + + module->ctx_index = ngx_module_ctx_index(cycle, type, next); + + if (module->ctx_index > max) { + max = module->ctx_index; + } + + next = module->ctx_index + 1; + } + + /* + * make sure the number returned is big enough for previous + * cycle as well, else there will be problems if the number + * will be stored in a global variable (as it's used to be) + * and we'll have to roll back to the previous cycle + */ + + if (cycle->old_cycle && cycle->old_cycle->modules) { + + for (i = 0; cycle->old_cycle->modules[i]; i++) { + module = cycle->old_cycle->modules[i]; + + if (module->type != type) { + continue; + } + + if (module->ctx_index > max) { + max = module->ctx_index; + } + } + } + + /* prevent loading of additional modules */ + + cycle->modules_used = 1; + + return max + 1; +} + + +ngx_int_t +ngx_add_module(ngx_conf_t *cf, ngx_str_t *file, ngx_module_t *module, + char **order) +{ + void *rv; + ngx_uint_t i, m, before; + ngx_core_module_t *core_module; + + if (cf->cycle->modules_n >= ngx_max_module) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "too many modules loaded"); + return NGX_ERROR; + } + + if (module->version != nginx_version) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "module \"%V\" version %ui instead of %ui", + file, module->version, nginx_version); + return NGX_ERROR; + } + + if (ngx_strcmp(module->signature, NGX_MODULE_SIGNATURE) != 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "module \"%V\" is not binary compatible", + file); + return NGX_ERROR; + } + + for (m = 0; cf->cycle->modules[m]; m++) { + if (ngx_strcmp(cf->cycle->modules[m]->name, module->name) == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "module \"%s\" is already loaded", + module->name); + return NGX_ERROR; + } + } + + /* + * if the module wasn't previously loaded, assign an index + */ + + if (module->index == NGX_MODULE_UNSET_INDEX) { + module->index = ngx_module_index(cf->cycle); + + if (module->index >= ngx_max_module) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "too many modules loaded"); + return NGX_ERROR; + } + } + + /* + * put the module into the cycle->modules array + */ + + before = cf->cycle->modules_n; + + if (order) { + for (i = 0; order[i]; i++) { + if (ngx_strcmp(order[i], module->name) == 0) { + i++; + break; + } + } + + for ( /* void */ ; order[i]; i++) { + +#if 0 + ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0, + "module: %s before %s", + module->name, order[i]); +#endif + + for (m = 0; m < before; m++) { + if (ngx_strcmp(cf->cycle->modules[m]->name, order[i]) == 0) { + + ngx_log_debug3(NGX_LOG_DEBUG_CORE, cf->log, 0, + "module: %s before %s:%i", + module->name, order[i], m); + + before = m; + break; + } + } + } + } + + /* put the module before modules[before] */ + + if (before != cf->cycle->modules_n) { + ngx_memmove(&cf->cycle->modules[before + 1], + &cf->cycle->modules[before], + (cf->cycle->modules_n - before) * sizeof(ngx_module_t *)); + } + + cf->cycle->modules[before] = module; + cf->cycle->modules_n++; + + if (module->type == NGX_CORE_MODULE) { + + /* + * we are smart enough to initialize core modules; + * other modules are expected to be loaded before + * initialization - e.g., http modules must be loaded + * before http{} block + */ + + core_module = module->ctx; + + if (core_module->create_conf) { + rv = core_module->create_conf(cf->cycle); + if (rv == NULL) { + return NGX_ERROR; + } + + cf->cycle->conf_ctx[module->index] = rv; + } + } + + return NGX_OK; +} + + +static ngx_uint_t +ngx_module_index(ngx_cycle_t *cycle) +{ + ngx_uint_t i, index; + ngx_module_t *module; + + index = 0; + +again: + + /* find an unused index */ + + for (i = 0; cycle->modules[i]; i++) { + module = cycle->modules[i]; + + if (module->index == index) { + index++; + goto again; + } + } + + /* check previous cycle */ + + if (cycle->old_cycle && cycle->old_cycle->modules) { + + for (i = 0; cycle->old_cycle->modules[i]; i++) { + module = cycle->old_cycle->modules[i]; + + if (module->index == index) { + index++; + goto again; + } + } + } + + return index; +} + + +static ngx_uint_t +ngx_module_ctx_index(ngx_cycle_t *cycle, ngx_uint_t type, ngx_uint_t index) +{ + ngx_uint_t i; + ngx_module_t *module; + +again: + + /* find an unused ctx_index */ + + for (i = 0; cycle->modules[i]; i++) { + module = cycle->modules[i]; + + if (module->type != type) { continue; } - cycle->modules[i]->ctx_index = max++; + if (module->ctx_index == index) { + index++; + goto again; + } + } + + /* check previous cycle */ + + if (cycle->old_cycle && cycle->old_cycle->modules) { + + for (i = 0; cycle->old_cycle->modules[i]; i++) { + module = cycle->old_cycle->modules[i]; + + if (module->type != type) { + continue; + } + + if (module->ctx_index == index) { + index++; + goto again; + } + } } - return max; + return index; } diff --git a/src/core/ngx_module.h b/src/core/ngx_module.h index fb5ac9b57..cd28c4973 100644 --- a/src/core/ngx_module.h +++ b/src/core/ngx_module.h @@ -12,9 +12,234 @@ #include <ngx_config.h> #include <ngx_core.h> +#include <nginx.h> -#define NGX_MODULE_V1 0, 0, 0, 0, 0, 0, 1 +#define NGX_MODULE_UNSET_INDEX (ngx_uint_t) -1 + + +#define NGX_MODULE_SIGNATURE_0 \ + ngx_value(NGX_PTR_SIZE) "," \ + ngx_value(NGX_SIG_ATOMIC_T_SIZE) "," \ + ngx_value(NGX_TIME_T_SIZE) "," + +#if (NGX_HAVE_KQUEUE) +#define NGX_MODULE_SIGNATURE_1 "1" +#else +#define NGX_MODULE_SIGNATURE_1 "0" +#endif + +#if (NGX_HAVE_IOCP) +#define NGX_MODULE_SIGNATURE_2 "1" +#else +#define NGX_MODULE_SIGNATURE_2 "0" +#endif + +#if (NGX_HAVE_FILE_AIO) +#define NGX_MODULE_SIGNATURE_3 "1" +#else +#define NGX_MODULE_SIGNATURE_3 "0" +#endif + +#if (NGX_HAVE_AIO_SENDFILE) +#define NGX_MODULE_SIGNATURE_4 "1" +#else +#define NGX_MODULE_SIGNATURE_4 "0" +#endif + +#if (NGX_HAVE_EVENTFD) +#define NGX_MODULE_SIGNATURE_5 "1" +#else +#define NGX_MODULE_SIGNATURE_5 "0" +#endif + +#if (NGX_HAVE_EPOLL) +#define NGX_MODULE_SIGNATURE_6 "1" +#else +#define NGX_MODULE_SIGNATURE_6 "0" +#endif + +#if (NGX_HAVE_KEEPALIVE_TUNABLE) +#define NGX_MODULE_SIGNATURE_7 "1" +#else +#define NGX_MODULE_SIGNATURE_7 "0" +#endif + +#if (NGX_HAVE_INET6) +#define NGX_MODULE_SIGNATURE_8 "1" +#else +#define NGX_MODULE_SIGNATURE_8 "0" +#endif + +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) +#define NGX_MODULE_SIGNATURE_9 "1" +#else +#define NGX_MODULE_SIGNATURE_9 "0" +#endif + +#if (NGX_HAVE_REUSEPORT) +#define NGX_MODULE_SIGNATURE_10 "1" +#else +#define NGX_MODULE_SIGNATURE_10 "0" +#endif + +#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) +#define NGX_MODULE_SIGNATURE_11 "1" +#else +#define NGX_MODULE_SIGNATURE_11 "0" +#endif + +#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) +#define NGX_MODULE_SIGNATURE_12 "1" +#else +#define NGX_MODULE_SIGNATURE_12 "0" +#endif + +#if (NGX_HAVE_SETFIB) +#define NGX_MODULE_SIGNATURE_13 "1" +#else +#define NGX_MODULE_SIGNATURE_13 "0" +#endif + +#if (NGX_HAVE_TCP_FASTOPEN) +#define NGX_MODULE_SIGNATURE_14 "1" +#else +#define NGX_MODULE_SIGNATURE_14 "0" +#endif + +#if (NGX_HAVE_UNIX_DOMAIN) +#define NGX_MODULE_SIGNATURE_15 "1" +#else +#define NGX_MODULE_SIGNATURE_15 "0" +#endif + +#if (NGX_HAVE_VARIADIC_MACROS) +#define NGX_MODULE_SIGNATURE_16 "1" +#else +#define NGX_MODULE_SIGNATURE_16 "0" +#endif + +#if (NGX_HAVE_MD5) +#define NGX_MODULE_SIGNATURE_17 "1" +#else +#define NGX_MODULE_SIGNATURE_17 "0" +#endif + +#if (NGX_HAVE_SHA1) +#define NGX_MODULE_SIGNATURE_18 "1" +#else +#define NGX_MODULE_SIGNATURE_18 "0" +#endif + +#if (NGX_HAVE_OPENAT) +#define NGX_MODULE_SIGNATURE_19 "1" +#else +#define NGX_MODULE_SIGNATURE_19 "0" +#endif + +#if (NGX_HAVE_ATOMIC_OPS) +#define NGX_MODULE_SIGNATURE_20 "1" +#else +#define NGX_MODULE_SIGNATURE_20 "0" +#endif + +#if (NGX_HAVE_POSIX_SEM) +#define NGX_MODULE_SIGNATURE_21 "1" +#else +#define NGX_MODULE_SIGNATURE_21 "0" +#endif + +#if (NGX_THREADS) +#define NGX_MODULE_SIGNATURE_22 "1" +#else +#define NGX_MODULE_SIGNATURE_22 "0" +#endif + +#if (NGX_PCRE) +#define NGX_MODULE_SIGNATURE_23 "1" +#else +#define NGX_MODULE_SIGNATURE_23 "0" +#endif + +#if (NGX_HTTP_SSL) +#define NGX_MODULE_SIGNATURE_24 "1" +#else +#define NGX_MODULE_SIGNATURE_24 "0" +#endif + +#if (NGX_HTTP_V2) +#define NGX_MODULE_SIGNATURE_25 "1" +#else +#define NGX_MODULE_SIGNATURE_25 "0" +#endif + +#if (NGX_HTTP_GZIP) +#define NGX_MODULE_SIGNATURE_26 "1" +#else +#define NGX_MODULE_SIGNATURE_26 "0" +#endif + +#if (NGX_HTTP_DEGRADATION) +#define NGX_MODULE_SIGNATURE_27 "1" +#else +#define NGX_MODULE_SIGNATURE_27 "0" +#endif + +#if (NGX_HTTP_X_FORWARDED_FOR) +#define NGX_MODULE_SIGNATURE_28 "1" +#else +#define NGX_MODULE_SIGNATURE_28 "0" +#endif + +#if (NGX_HTTP_REALIP) +#define NGX_MODULE_SIGNATURE_29 "1" +#else +#define NGX_MODULE_SIGNATURE_29 "0" +#endif + +#if (NGX_HTTP_HEADERS) +#define NGX_MODULE_SIGNATURE_30 "1" +#else +#define NGX_MODULE_SIGNATURE_30 "0" +#endif + +#if (NGX_HTTP_DAV) +#define NGX_MODULE_SIGNATURE_31 "1" +#else +#define NGX_MODULE_SIGNATURE_31 "0" +#endif + +#if (NGX_HTTP_CACHE) +#define NGX_MODULE_SIGNATURE_32 "1" +#else +#define NGX_MODULE_SIGNATURE_32 "0" +#endif + +#if (NGX_HTTP_UPSTREAM_ZONE) +#define NGX_MODULE_SIGNATURE_33 "1" +#else +#define NGX_MODULE_SIGNATURE_33 "0" +#endif + +#define NGX_MODULE_SIGNATURE \ + NGX_MODULE_SIGNATURE_0 NGX_MODULE_SIGNATURE_1 NGX_MODULE_SIGNATURE_2 \ + NGX_MODULE_SIGNATURE_3 NGX_MODULE_SIGNATURE_4 NGX_MODULE_SIGNATURE_5 \ + NGX_MODULE_SIGNATURE_6 NGX_MODULE_SIGNATURE_7 NGX_MODULE_SIGNATURE_8 \ + NGX_MODULE_SIGNATURE_9 NGX_MODULE_SIGNATURE_10 NGX_MODULE_SIGNATURE_11 \ + NGX_MODULE_SIGNATURE_12 NGX_MODULE_SIGNATURE_13 NGX_MODULE_SIGNATURE_14 \ + NGX_MODULE_SIGNATURE_15 NGX_MODULE_SIGNATURE_16 NGX_MODULE_SIGNATURE_17 \ + NGX_MODULE_SIGNATURE_18 NGX_MODULE_SIGNATURE_19 NGX_MODULE_SIGNATURE_20 \ + NGX_MODULE_SIGNATURE_21 NGX_MODULE_SIGNATURE_22 NGX_MODULE_SIGNATURE_23 \ + NGX_MODULE_SIGNATURE_24 NGX_MODULE_SIGNATURE_25 NGX_MODULE_SIGNATURE_26 \ + NGX_MODULE_SIGNATURE_27 NGX_MODULE_SIGNATURE_28 NGX_MODULE_SIGNATURE_29 \ + NGX_MODULE_SIGNATURE_30 NGX_MODULE_SIGNATURE_31 NGX_MODULE_SIGNATURE_32 \ + NGX_MODULE_SIGNATURE_33 + + +#define NGX_MODULE_V1 \ + NGX_MODULE_UNSET_INDEX, NGX_MODULE_UNSET_INDEX, \ + NULL, 0, 0, nginx_version, NGX_MODULE_SIGNATURE + #define NGX_MODULE_V1_PADDING 0, 0, 0, 0, 0, 0, 0, 0 @@ -22,12 +247,13 @@ struct ngx_module_s { ngx_uint_t ctx_index; ngx_uint_t index; + char *name; + ngx_uint_t spare0; ngx_uint_t spare1; - ngx_uint_t spare2; - ngx_uint_t spare3; ngx_uint_t version; + char *signature; void *ctx; ngx_command_t *commands; @@ -63,12 +289,19 @@ typedef struct { ngx_int_t ngx_preinit_modules(); +ngx_int_t ngx_cycle_modules(ngx_cycle_t *cycle); ngx_int_t ngx_init_modules(ngx_cycle_t *cycle); ngx_int_t ngx_count_modules(ngx_cycle_t *cycle, ngx_uint_t type); +ngx_int_t ngx_add_module(ngx_conf_t *cf, ngx_str_t *file, + ngx_module_t *module, char **order); + + extern ngx_module_t *ngx_modules[]; extern ngx_uint_t ngx_max_module; +extern char *ngx_module_names[]; + #endif /* _NGX_MODULE_H_INCLUDED_ */ |