small-package/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.c

1000 lines
27 KiB
C

/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include "ngx_rtmp.h"
#include "ngx_rtmp_dynamic.h"
static void *ngx_rtmp_dynamic_create_conf(ngx_conf_t *cf);
static void *ngx_rtmp_dynamic_core_create_main_conf(ngx_conf_t *cf);
static char *ngx_rtmp_dynamic_core_init_main_conf(ngx_conf_t *cf, void *conf);
static void *ngx_rtmp_dynamic_core_create_srv_conf(ngx_conf_t *cf);
static char *ngx_rtmp_dynamic_core_init_srv_conf(ngx_conf_t *cf, void *conf);
static void *ngx_rtmp_dynamic_core_create_app_conf(ngx_conf_t *cf);
static char *ngx_rtmp_dynamic_core_init_app_conf(ngx_conf_t *cf, void *conf);
static char *ngx_rtmp_dynamic_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_rtmp_dynamic_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_rtmp_dynamic_core_server_name(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
static char *ngx_rtmp_dynamic_core_application(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
typedef struct {
ngx_str_t name;
ngx_map_node_t node;
void **app_conf;
} ngx_rtmp_dynamic_core_app_conf_t;
typedef struct {
/* array of the ngx_rtmp_server_name_t, "server_name" directive */
ngx_array_t server_names;
ngx_rtmp_dynamic_core_app_conf_t *default_app;
ngx_map_t app_conf;
void **srv_conf;
} ngx_rtmp_dynamic_core_srv_conf_t;
typedef struct {
#if (NGX_PCRE)
ngx_dynamic_regex_t *regex;
#endif
ngx_rtmp_dynamic_core_srv_conf_t *server; /* virtual name server conf */
ngx_str_t name;
} ngx_rtmp_dynamic_server_name_t;
typedef struct {
/* ngx_rtmp_dynamic_srv_conf_t */
ngx_array_t servers;
ngx_uint_t server_names_hash_max_size;
ngx_uint_t server_names_hash_bucket_size;
/* the default server configuration for this address:port */
ngx_rtmp_dynamic_core_srv_conf_t *default_server;
ngx_hash_combined_t names;
#if (NGX_PCRE)
ngx_uint_t nregex;
ngx_rtmp_dynamic_server_name_t *regex;
#endif
} ngx_rtmp_dynamic_core_main_conf_t;
typedef struct {
void **main_conf;
} ngx_rtmp_dynamic_conf_t;
static ngx_core_module_t ngx_rtmp_dynamic_module_ctx = {
ngx_string("rtmp_dynamic"),
NULL,
NULL
};
static ngx_command_t ngx_rtmp_dynamic_dcommands[] = {
{ ngx_string("rtmp"),
NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_rtmp_dynamic_block,
0,
0,
NULL },
ngx_null_command
};
static ngx_dynamic_core_module_t ngx_rtmp_dynamic_module_dctx = {
ngx_string("rtmp_dynamic"),
ngx_rtmp_dynamic_create_conf,
NULL
};
ngx_module_t ngx_rtmp_dynamic_module = {
NGX_MODULE_V1,
&ngx_rtmp_dynamic_module_ctx, /* module context */
NULL, /* module directives */
NGX_CORE_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
(uintptr_t) &ngx_rtmp_dynamic_module_dctx, /* module dynamic context */
(uintptr_t) ngx_rtmp_dynamic_dcommands, /* module dynamic directives */
NGX_MODULE_V1_DYNAMIC_PADDING
};
static ngx_rtmp_module_t ngx_rtmp_dynamic_core_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create application configuration */
NULL /* merge application configuration */
};
static ngx_command_t ngx_rtmp_dynamic_core_dcommands[] = {
{ ngx_string("server_names_hash_max_size"),
NGX_RTMP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
0,
offsetof(ngx_rtmp_dynamic_core_main_conf_t, server_names_hash_max_size),
NULL },
{ ngx_string("server_names_hash_bucket_size"),
NGX_RTMP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
0,
offsetof(ngx_rtmp_dynamic_core_main_conf_t,
server_names_hash_bucket_size),
NULL },
{ ngx_string("server"),
NGX_RTMP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
ngx_rtmp_dynamic_core_server,
0,
0,
NULL },
{ ngx_string("server_name"),
NGX_RTMP_SRV_CONF|NGX_CONF_1MORE,
ngx_rtmp_dynamic_core_server_name,
0,
0,
NULL },
{ ngx_string("application"),
NGX_RTMP_SRV_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12,
ngx_rtmp_dynamic_core_application,
0,
0,
NULL },
ngx_null_command
};
static ngx_rtmp_dynamic_module_t ngx_rtmp_dynamic_core_module_dctx = {
ngx_rtmp_dynamic_core_create_main_conf, /* create main configuration */
ngx_rtmp_dynamic_core_init_main_conf, /* init main configuration */
ngx_rtmp_dynamic_core_create_srv_conf, /* create srv configuration */
ngx_rtmp_dynamic_core_init_srv_conf, /* init srv configuration */
ngx_rtmp_dynamic_core_create_app_conf, /* create app configuration */
ngx_rtmp_dynamic_core_init_app_conf /* init app configuration */
};
ngx_module_t ngx_rtmp_dynamic_core_module = {
NGX_MODULE_V1,
&ngx_rtmp_dynamic_core_module_ctx, /* module context */
NULL, /* module directives */
NGX_RTMP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
(uintptr_t) &ngx_rtmp_dynamic_core_module_dctx, /* module dynamic context */
(uintptr_t) ngx_rtmp_dynamic_core_dcommands, /* module dynamic directives */
NGX_MODULE_V1_DYNAMIC_PADDING
};
static void *
ngx_rtmp_dynamic_create_conf(ngx_conf_t *cf)
{
ngx_rtmp_dynamic_conf_t *rdccf;
rdccf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_dynamic_conf_t));
if (rdccf == NULL) {
return NULL;
}
return rdccf;
}
static void *
ngx_rtmp_dynamic_core_create_main_conf(ngx_conf_t *cf)
{
ngx_rtmp_dynamic_core_main_conf_t *rdcmcf;
rdcmcf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_dynamic_core_main_conf_t));
if (rdcmcf == NULL) {
return NULL;
}
if (ngx_array_init(&rdcmcf->servers, cf->pool, 4,
sizeof(ngx_rtmp_dynamic_core_srv_conf_t *)) != NGX_OK)
{
return NULL;
}
rdcmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT;
rdcmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT;
return rdcmcf;
}
static char *
ngx_rtmp_dynamic_core_init_main_conf(ngx_conf_t *cf, void *conf)
{
ngx_rtmp_dynamic_core_main_conf_t *rdcmcf;
rdcmcf = conf;
ngx_conf_init_uint_value(rdcmcf->server_names_hash_max_size, 512);
ngx_conf_init_uint_value(rdcmcf->server_names_hash_bucket_size,
ngx_cacheline_size);
return NGX_CONF_OK;
}
static void *
ngx_rtmp_dynamic_core_create_srv_conf(ngx_conf_t *cf)
{
ngx_rtmp_dynamic_core_srv_conf_t *rdcscf;
rdcscf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_dynamic_core_srv_conf_t));
if (rdcscf == NULL) {
return NULL;
}
if (ngx_array_init(&rdcscf->server_names, cf->pool, 4,
sizeof(ngx_rtmp_dynamic_server_name_t)) != NGX_OK)
{
return NULL;
}
return rdcscf;
}
static char *
ngx_rtmp_dynamic_core_init_srv_conf(ngx_conf_t *cf, void *conf)
{
return NGX_CONF_OK;
}
static void *
ngx_rtmp_dynamic_core_create_app_conf(ngx_conf_t *cf)
{
ngx_rtmp_dynamic_core_app_conf_t *rdcacf;
rdcacf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_dynamic_core_app_conf_t));
if (rdcacf == NULL) {
return NULL;
}
return rdcacf;
}
static char *
ngx_rtmp_dynamic_core_init_app_conf(ngx_conf_t *cf, void *conf)
{
return NGX_CONF_OK;
}
static ngx_int_t
ngx_rtmp_dynamic_core_find_application(ngx_rtmp_session_t *s,
ngx_rtmp_dynamic_core_srv_conf_t *rdcscf,
ngx_rtmp_dynamic_core_app_conf_t **rdcacf)
{
ngx_map_node_t *node;
node = ngx_map_find(&rdcscf->app_conf, (intptr_t) &s->app);
if (node == NULL) {
*rdcacf = rdcscf->default_app;
} else {
*rdcacf = (ngx_rtmp_dynamic_core_app_conf_t *)
((char *) node - offsetof(ngx_rtmp_dynamic_core_app_conf_t, node));
}
return NGX_OK;
}
static ngx_int_t
ngx_rtmp_dynamic_core_init_virtual_servers(ngx_conf_t *cf,
ngx_rtmp_dynamic_conf_t *hdcf)
{
ngx_rtmp_dynamic_core_main_conf_t *rdcmcf;
ngx_rtmp_dynamic_core_srv_conf_t **rdcscfp;
ngx_hash_init_t hash;
ngx_hash_keys_arrays_t ha;
ngx_rtmp_dynamic_server_name_t *name;
ngx_uint_t s, n;
ngx_int_t rc;
#if (NGX_PCRE)
ngx_uint_t regex, i;
regex = 0;
#endif
rdcmcf = hdcf->main_conf[ngx_rtmp_dynamic_core_module.ctx_index];
ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
ha.temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log);
if (ha.temp_pool == NULL) {
return NGX_ERROR;
}
ha.pool = cf->pool;
if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
goto failed;
}
rdcscfp = rdcmcf->servers.elts;
rdcmcf->default_server = rdcscfp[0];
for (s = 0; s < rdcmcf->servers.nelts; ++s) {
name = rdcscfp[s]->server_names.elts;
for (n = 0; n < rdcscfp[s]->server_names.nelts; ++n) {
#if (NGX_PCRE)
if (name[n].regex) {
++regex;
continue;
}
#endif
rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server,
NGX_HASH_WILDCARD_KEY);
if (rc == NGX_ERROR) {
return NGX_ERROR;
}
if (rc == NGX_DECLINED) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"invalid server name or wildcard \"%V\"",
&name[n].name);
return NGX_ERROR;
}
if (rc == NGX_BUSY) {
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
"conflicting server name \"%V\", ignored",
&name[n].name);
}
}
}
hash.key = ngx_hash_key_lc;
hash.max_size = rdcmcf->server_names_hash_max_size;
hash.bucket_size = rdcmcf->server_names_hash_bucket_size;
hash.name = "rtmp_dynamic_server_names_hash";
hash.pool = cf->pool;
if (ha.keys.nelts) {
hash.hash = &rdcmcf->names.hash;
hash.temp_pool = NULL;
if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
goto failed;
}
}
if (ha.dns_wc_head.nelts) {
ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
sizeof(ngx_hash_key_t), ngx_dynamic_cmp_dns_wildcards);
hash.hash = NULL;
hash.temp_pool = ha.temp_pool;
if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
ha.dns_wc_head.nelts) != NGX_OK)
{
goto failed;
}
rdcmcf->names.wc_head = (ngx_hash_wildcard_t *) hash.hash;
}
if (ha.dns_wc_tail.nelts) {
ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
sizeof(ngx_hash_key_t), ngx_dynamic_cmp_dns_wildcards);
hash.hash = NULL;
hash.temp_pool = ha.temp_pool;
if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
ha.dns_wc_tail.nelts) != NGX_OK)
{
goto failed;
}
rdcmcf->names.wc_tail = (ngx_hash_wildcard_t *) hash.hash;
}
ngx_destroy_pool(ha.temp_pool);
#if (NGX_PCRE)
if (regex == 0) {
return NGX_OK;
}
rdcmcf->nregex = regex;
rdcmcf->regex = ngx_pcalloc(cf->pool,
regex * sizeof(ngx_rtmp_dynamic_server_name_t));
if (rdcmcf->regex == NULL) {
return NGX_ERROR;
}
i = 0;
for (s = 0; s < rdcmcf->servers.nelts; ++s) {
name = rdcscfp[s]->server_names.elts;
for (n = 0; n < rdcscfp[s]->server_names.nelts; ++n) {
if (name[n].regex) {
rdcmcf->regex[i++] = name[n];
}
}
}
#endif
return NGX_OK;
failed:
ngx_destroy_pool(ha.temp_pool);
return NGX_ERROR;
}
static ngx_int_t
ngx_rtmp_dynamic_core_find_virtual_server(ngx_str_t *server,
ngx_rtmp_dynamic_core_main_conf_t *rdcmcf,
ngx_rtmp_dynamic_core_srv_conf_t **rdcscfp)
{
ngx_rtmp_dynamic_core_srv_conf_t *rdcscf;
rdcscf = ngx_hash_find_combined(&rdcmcf->names,
ngx_hash_key(server->data, server->len),
server->data, server->len);
if (rdcscf) {
*rdcscfp = rdcscf;
return NGX_OK;
}
#if (NGX_PCRE)
if (server->len && rdcmcf->nregex) {
ngx_int_t n;
ngx_uint_t i;
ngx_rtmp_dynamic_server_name_t *sn;
sn = rdcmcf->regex;
for (i = 0; i < rdcmcf->nregex; ++i) {
n = ngx_regex_exec(sn[i].regex->regex, server, NULL, 0);
if (n == NGX_REGEX_NO_MATCHED) {
continue;
}
if (n >= 0) {
*rdcscfp = sn[i].server;
return NGX_OK;
}
return NGX_ERROR;
}
}
#endif
return NGX_DECLINED;
}
static char *
ngx_rtmp_dynamic_core_application(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
ngx_rtmp_dynamic_module_t *module;
ngx_rtmp_dynamic_core_app_conf_t *rdcacf;
ngx_rtmp_dynamic_core_srv_conf_t *rdcscf;
ngx_conf_t pcf;
void *mconf, **app_conf;
ngx_uint_t i, ci;
ngx_str_t *value;
char *rv = NULL;
rdcscf = conf;
/* app_conf is temp cause hdclcf does not created now */
app_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module);
if (app_conf == NULL) {
return NGX_CONF_ERROR;
}
for (i = 0; cf->cycle->modules[i]; ++i) {
if (cf->cycle->modules[i]->type != NGX_RTMP_MODULE) {
continue;
}
module = (ngx_rtmp_dynamic_module_t *)
cf->cycle->modules[i]->spare_hook0;
if (module == NULL) {
continue;
}
if (module->create_app_conf) {
mconf = module->create_app_conf(cf);
if (mconf == NULL) {
return NGX_CONF_ERROR;
}
app_conf[cf->cycle->modules[i]->ctx_index] = mconf;
}
}
rdcacf = app_conf[ngx_rtmp_dynamic_core_module.ctx_index];
rdcacf->app_conf = app_conf;
value = cf->args->elts;
rdcacf->name = value[1];
if (rdcacf->name.len == 1 && rdcacf->name.data[0] == '*') { /* default */
if (rdcscf->default_app) {
return "is duplicate";
}
rdcscf->default_app = rdcacf;
} else {
rdcacf->node.raw_key = (intptr_t) &rdcacf->name;
ngx_map_insert(&rdcscf->app_conf, &rdcacf->node, 0);
}
pcf = *cf;
cf->ctx = rdcacf->app_conf;
cf->cmd_type = NGX_RTMP_APP_CONF;
if (ngx_dynamic_conf_parse(cf, 0) != NGX_OK) {
goto failed;
}
for (i = 0; cf->cycle->modules[i]; ++i) {
if (cf->cycle->modules[i]->type != NGX_RTMP_MODULE) {
continue;
}
module = (ngx_rtmp_dynamic_module_t *)
cf->cycle->modules[i]->spare_hook0;
ci = cf->cycle->modules[i]->ctx_index;
if (module == NULL) {
continue;
}
if (module->init_app_conf) {
rv = module->init_app_conf(cf, rdcacf->app_conf[ci]);
if (rv != NGX_CONF_OK) {
goto failed;
}
}
}
*cf = pcf;
return NGX_CONF_OK;
failed:
*cf = pcf;
if (rv) {
return rv;
}
return NGX_CONF_ERROR;
}
static char *
ngx_rtmp_dynamic_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
ngx_rtmp_dynamic_core_srv_conf_t *rdcscf;
u_char ch;
ngx_str_t *value;
ngx_uint_t i;
ngx_rtmp_dynamic_server_name_t *sn;
rdcscf = conf;
value = cf->args->elts;
for (i = 1; i < cf->args->nelts; i++) {
ch = value[i].data[0];
if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.'))
|| (ch == '.' && value[i].len < 2))
{
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"server name \"%V\" is invalid", &value[i]);
return NGX_CONF_ERROR;
}
if (ngx_strchr(value[i].data, '/')) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"server name \"%V\" has suspicious symbols",
&value[i]);
}
sn = ngx_array_push(&rdcscf->server_names);
if (sn == NULL) {
return NGX_CONF_ERROR;
}
#if (NGX_PCRE)
sn->regex = NULL;
#endif
sn->server = rdcscf;
if (ngx_strcasecmp(value[i].data, (u_char *) "$hostname") == 0) {
sn->name = cf->cycle->hostname;
} else {
sn->name = value[i];
}
if (value[i].data[0] != '~') {
ngx_strlow(sn->name.data, sn->name.data, sn->name.len);
continue;
}
#if (NGX_PCRE)
{
u_char *p;
ngx_regex_compile_t rc;
u_char errstr[NGX_MAX_CONF_ERRSTR];
if (value[i].len == 1) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"empty regex in server name \"%V\"", &value[i]);
return NGX_CONF_ERROR;
}
value[i].len--;
value[i].data++;
ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
rc.pattern = value[i];
rc.err.len = NGX_MAX_CONF_ERRSTR;
rc.err.data = errstr;
for (p = value[i].data; p < value[i].data + value[i].len; p++) {
if (*p >= 'A' && *p <= 'Z') {
rc.options = NGX_REGEX_CASELESS;
break;
}
}
sn->regex = ngx_dynamic_regex_compile(cf, &rc);
if (sn->regex == NULL) {
return NGX_CONF_ERROR;
}
sn->name = value[i];
}
#else
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"using regex \"%V\" "
"requires PCRE library", &value[i]);
return NGX_CONF_ERROR;
#endif
}
return NGX_CONF_OK;
}
static char *
ngx_rtmp_dynamic_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_rtmp_dynamic_module_t *module;
ngx_rtmp_dynamic_core_main_conf_t *rdcmcf;
ngx_rtmp_dynamic_core_srv_conf_t *rdcscf, **rdcscfp;
ngx_conf_t pcf;
void *mconf, **srv_conf;
ngx_uint_t i, ci;
char *rv = NULL;
rdcmcf = conf;
/* srv_conf is temp cause hdcscf does not created now */
srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module);
if (srv_conf == NULL) {
return NGX_CONF_ERROR;
}
for (i = 0; cf->cycle->modules[i]; ++i) {
if (cf->cycle->modules[i]->type != NGX_RTMP_MODULE) {
continue;
}
module = (ngx_rtmp_dynamic_module_t *)
cf->cycle->modules[i]->spare_hook0;
if (module == NULL) {
continue;
}
if (module->create_srv_conf) {
mconf = module->create_srv_conf(cf);
if (mconf == NULL) {
return NGX_CONF_ERROR;
}
srv_conf[cf->cycle->modules[i]->ctx_index] = mconf;
}
}
rdcscf = srv_conf[ngx_rtmp_dynamic_core_module.ctx_index];
rdcscf->srv_conf = srv_conf;
ngx_map_init(&rdcscf->app_conf, ngx_map_hash_str, ngx_cmp_str);
/* save hdcscf into hdcmcf */
rdcscfp = ngx_array_push(&rdcmcf->servers);
if (rdcscfp == NULL) {
return NGX_CONF_ERROR;
}
*rdcscfp = rdcscf;
pcf = *cf;
cf->ctx = rdcscf->srv_conf;
cf->cmd_type = NGX_RTMP_SRV_CONF;
if (ngx_dynamic_conf_parse(cf, 0) != NGX_OK) {
goto failed;
}
for (i = 0; cf->cycle->modules[i]; ++i) {
if (cf->cycle->modules[i]->type != NGX_RTMP_MODULE) {
continue;
}
module = (ngx_rtmp_dynamic_module_t *)
cf->cycle->modules[i]->spare_hook0;
ci = cf->cycle->modules[i]->ctx_index;
if (module == NULL) {
continue;
}
if (module->init_srv_conf) {
rv = module->init_srv_conf(cf, rdcscf->srv_conf[ci]);
if (rv != NGX_CONF_OK) {
goto failed;
}
}
}
*cf = pcf;
return NGX_CONF_OK;
failed:
*cf = pcf;
if (rv) {
return rv;
}
return NGX_CONF_ERROR;
}
static char *
ngx_rtmp_dynamic_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_rtmp_dynamic_conf_t *rdccf;
ngx_rtmp_dynamic_module_t *module;
ngx_conf_t pcf;
ngx_uint_t i, ci;
char *rv = NULL;
rdccf = conf;
/* create main_conf ctx */
rdccf->main_conf = ngx_pcalloc(cf->pool, sizeof(void *)
* ngx_rtmp_max_module);
if (rdccf->main_conf == NULL) {
return NGX_CONF_ERROR;
}
/* create http dynamic conf for all http module */
for (i = 0; cf->cycle->modules[i]; ++i) {
if (cf->cycle->modules[i]->type != NGX_RTMP_MODULE) {
continue;
}
module = (ngx_rtmp_dynamic_module_t *)
cf->cycle->modules[i]->spare_hook0;
ci = cf->cycle->modules[i]->ctx_index;
if (module == NULL) {
continue;
}
if (module->create_main_conf) {
rdccf->main_conf[ci] = module->create_main_conf(cf);
if (rdccf->main_conf[ci] == NULL) {
return NGX_CONF_ERROR;
}
}
}
/* save conf for recovery */
pcf = *cf;
cf->ctx = rdccf->main_conf;
cf->module_type = NGX_RTMP_MODULE;
cf->cmd_type = NGX_RTMP_MAIN_CONF;
if (ngx_dynamic_conf_parse(cf, 0) != NGX_OK) {
goto failed;
}
for (i = 0; cf->cycle->modules[i]; ++i) {
if (cf->cycle->modules[i]->type != NGX_RTMP_MODULE) {
continue;
}
module = (ngx_rtmp_dynamic_module_t *)
cf->cycle->modules[i]->spare_hook0;
ci = cf->cycle->modules[i]->ctx_index;
if (module == NULL) {
continue;
}
if (module->init_main_conf) {
rv = module->init_main_conf(cf, rdccf->main_conf[ci]);
if (rv != NGX_CONF_OK) {
goto failed;
}
}
}
if (ngx_rtmp_dynamic_core_init_virtual_servers(cf, rdccf) != NGX_OK) {
goto failed;
}
*cf = pcf;
return NGX_CONF_OK;
failed:
*cf = pcf;
if (rv) {
return rv;
}
return NGX_CONF_ERROR;
}
/* interface from here */
void *
ngx_rtmp_get_module_main_dconf(ngx_rtmp_session_t *s, ngx_module_t *m)
{
ngx_rtmp_dynamic_conf_t *rdcf;
rdcf = ngx_get_dconf(&ngx_rtmp_dynamic_module);
if (rdcf == NULL || rdcf->main_conf == NULL) {
return NULL;
}
return rdcf->main_conf[m->ctx_index];
}
void *
ngx_rtmp_get_module_srv_dconf(ngx_rtmp_session_t *s, ngx_module_t *m)
{
ngx_rtmp_dynamic_core_main_conf_t *rdcmcf;
ngx_rtmp_dynamic_core_srv_conf_t *rdcscf;
ngx_int_t rc;
rdcmcf = ngx_rtmp_get_module_main_dconf(s, &ngx_rtmp_dynamic_core_module);
if (rdcmcf == NULL) {
return NULL;
}
rc = ngx_rtmp_dynamic_core_find_virtual_server(&s->domain, rdcmcf, &rdcscf);
switch (rc) {
case NGX_ERROR:
return NULL;
case NGX_DECLINED: /* virtual server not found */
return rdcmcf->default_server->srv_conf[m->ctx_index];
default:
return rdcscf->srv_conf[m->ctx_index];
}
}
void *
ngx_rtmp_get_module_app_dconf(ngx_rtmp_session_t *s, ngx_module_t *m)
{
ngx_rtmp_dynamic_core_srv_conf_t *rdcscf;
ngx_rtmp_dynamic_core_app_conf_t *rdcacf;
ngx_int_t rc;
rdcscf = ngx_rtmp_get_module_srv_dconf(s, &ngx_rtmp_dynamic_core_module);
if (rdcscf == NULL) {
return NULL;
}
rdcacf = NULL;
rc = ngx_rtmp_dynamic_core_find_application(s, rdcscf, &rdcacf);
if (rc == NGX_ERROR) {
return NULL;
}
if (rdcacf) {
return rdcacf->app_conf[m->ctx_index];
}
return NULL;
}
void
ngx_rmtp_get_serverid_by_domain(ngx_str_t *serverid, ngx_str_t *domain)
{
ngx_rtmp_dynamic_conf_t *rdcf;
ngx_rtmp_dynamic_core_main_conf_t *rdcmcf;
ngx_rtmp_dynamic_core_srv_conf_t *rdcscf;
ngx_rtmp_core_srv_dconf_t *rcsdcf;
rdcf = ngx_get_dconf(&ngx_rtmp_dynamic_module);
if (rdcf == NULL || rdcf->main_conf) {
goto notfound;
}
rdcmcf = rdcf->main_conf[ngx_rtmp_dynamic_core_module.ctx_index];
if (rdcmcf == NULL) {
goto notfound;
}
ngx_rtmp_dynamic_core_find_virtual_server(domain, rdcmcf, &rdcscf);
if (rdcscf && rdcscf->srv_conf) {
rcsdcf = rdcscf->srv_conf[ngx_rtmp_core_module.ctx_index];
if (rcsdcf && rcsdcf->serverid.len) {
*serverid = rcsdcf->serverid;
return;
}
}
notfound:
*serverid = *domain;
}