diff options
author | Terry Wilson <twilson@digium.com> | 2012-06-01 16:33:25 +0000 |
---|---|---|
committer | Terry Wilson <twilson@digium.com> | 2012-06-01 16:33:25 +0000 |
commit | d54717c39e62f4cc8b290ac4836c4d4469d87c24 (patch) | |
tree | 5a765e82be880f3b8c2407133fbcc15c4b4349d0 /main/udptl.c | |
parent | 463f9d729aed1a5ed538aa3deed1a3fed9462111 (diff) |
Add new config-parsing framework
This framework adds a way to register the various options in a config
file with Asterisk and to handle loading and reloading of that config
in a consistent and atomic manner.
Review: https://reviewboard.asterisk.org/r/1873/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@368181 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/udptl.c')
-rw-r--r-- | main/udptl.c | 288 |
1 files changed, 179 insertions, 109 deletions
diff --git a/main/udptl.c b/main/udptl.c index 01401617a..a550ff16f 100644 --- a/main/udptl.c +++ b/main/udptl.c @@ -61,7 +61,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/frame.h" #include "asterisk/channel.h" #include "asterisk/acl.h" -#include "asterisk/config.h" +#include "asterisk/config_options.h" #include "asterisk/lock.h" #include "asterisk/utils.h" #include "asterisk/netsock2.h" @@ -82,16 +82,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #define DEFAULT_UDPTLSTART 4000 #define DEFAULT_UDPTLEND 4999 -static int udptlstart = DEFAULT_UDPTLSTART; -static int udptlend = DEFAULT_UDPTLEND; static int udptldebug; /*!< Are we debugging? */ static struct ast_sockaddr udptldebugaddr; /*!< Debug packets to/from this host */ -#ifdef SO_NO_CHECK -static int nochecksums; -#endif -static int udptlfecentries; -static int udptlfecspan; -static int use_even_ports; #define LOCAL_FAX_MAX_DATAGRAM 1400 #define DEFAULT_FAX_MAX_DATAGRAM 400 @@ -182,6 +174,43 @@ struct ast_udptl { static AST_RWLIST_HEAD_STATIC(protos, ast_udptl_protocol); +struct udptl_global_options { + unsigned int start; /*< The UDPTL start port */ + unsigned int end; /*< The UDPTL end port */ + unsigned int fecentries; + unsigned int fecspan; + unsigned int nochecksums; + unsigned int use_even_ports; +}; + +static AO2_GLOBAL_OBJ_STATIC(globals); + +struct udptl_config { + struct udptl_global_options *general; +}; + +static void *udptl_snapshot_alloc(void); +static int udptl_pre_apply_config(void); + +static struct aco_type general_option = { + .type = ACO_GLOBAL, + .category_match = ACO_WHITELIST, + .item_offset = offsetof(struct udptl_config, general), + .category = "^general$", +}; + +static struct aco_type *general_options[] = ACO_TYPES(&general_option); + +static struct aco_file udptl_conf = { + .filename = "udptl.conf", + .types = ACO_TYPES(&general_option), +}; + +CONFIG_INFO_STANDARD(cfg_info, globals, udptl_snapshot_alloc, + .files = ACO_FILES(&udptl_conf), + .pre_apply_config = udptl_pre_apply_config, +); + static inline int udptl_debug_test_addr(const struct ast_sockaddr *addr) { if (udptldebug == 0) @@ -922,12 +951,19 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct ast_sched_context *sched, s int startplace; int i; long int flags; + RAII_VAR(struct udptl_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup); + + if (!cfg || !cfg->general) { + ast_log(LOG_ERROR, "Could not access global udptl options!\n"); + return NULL; + } - if (!(udptl = ast_calloc(1, sizeof(*udptl)))) + if (!(udptl = ast_calloc(1, sizeof(*udptl)))) { return NULL; + } - udptl->error_correction_span = udptlfecspan; - udptl->error_correction_entries = udptlfecentries; + udptl->error_correction_span = cfg->general->fecspan; + udptl->error_correction_entries = cfg->general->fecentries; udptl->far_max_datagram = -1; udptl->far_max_ifp = -1; @@ -947,13 +983,15 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct ast_sched_context *sched, s } flags = fcntl(udptl->fd, F_GETFL); fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK); + #ifdef SO_NO_CHECK - if (nochecksums) - setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); + if (cfg->general->nochecksums) + setsockopt(udptl->fd, SOL_SOCKET, SO_NO_CHECK, &cfg->general->nochecksums, sizeof(cfg->general->nochecksums)); #endif + /* Find us a place */ - x = (udptlstart == udptlend) ? udptlstart : (ast_random() % (udptlend - udptlstart)) + udptlstart; - if (use_even_ports && (x & 1)) { + x = (cfg->general->start == cfg->general->end) ? cfg->general->start : (ast_random() % (cfg->general->end - cfg->general->start)) + cfg->general->start; + if (cfg->general->use_even_ports && (x & 1)) { ++x; } startplace = x; @@ -969,13 +1007,13 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct ast_sched_context *sched, s ast_free(udptl); return NULL; } - if (use_even_ports) { + if (cfg->general->use_even_ports) { x += 2; } else { ++x; } - if (x > udptlend) - x = udptlstart; + if (x > cfg->general->end) + x = cfg->general->start; if (x == startplace) { ast_log(LOG_WARNING, "No UDPTL ports remaining\n"); close(udptl->fd); @@ -989,6 +1027,7 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct ast_sched_context *sched, s udptl->io = io; udptl->ioid = ast_io_add(udptl->io, udptl->fd, udptlread, AST_IO_IN, udptl); } + return udptl; } @@ -1303,109 +1342,110 @@ static char *handle_cli_udptl_set_debug(struct ast_cli_entry *e, int cmd, struct return CLI_SUCCESS; } +static char *handle_cli_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + RAII_VAR(struct udptl_config *, cfg, NULL, ao2_cleanup); + + switch (cmd) { + case CLI_INIT: + e->command = "udptl show config"; + e->usage = + "Usage: udptl show config\n" + " Display UDPTL configuration options\n"; + return NULL; + case CLI_GENERATE: + return NULL; + } + + if (!(cfg = ao2_global_obj_ref(globals))) { + return CLI_FAILURE; + } + + ast_cli(a->fd, "UDPTL Global options\n"); + ast_cli(a->fd, "--------------------\n"); + ast_cli(a->fd, "udptlstart: %u\n", cfg->general->start); + ast_cli(a->fd, "udptlend: %u\n", cfg->general->end); + ast_cli(a->fd, "udptlfecentries: %u\n", cfg->general->fecentries); + ast_cli(a->fd, "udptlfecspan: %u\n", cfg->general->fecspan); + ast_cli(a->fd, "use_even_ports: %s\n", AST_CLI_YESNO(cfg->general->use_even_ports)); + ast_cli(a->fd, "udptlchecksums: %s\n", AST_CLI_YESNO(!cfg->general->nochecksums)); + + return CLI_SUCCESS; +} static struct ast_cli_entry cli_udptl[] = { - AST_CLI_DEFINE(handle_cli_udptl_set_debug, "Enable/Disable UDPTL debugging") + AST_CLI_DEFINE(handle_cli_udptl_set_debug, "Enable/Disable UDPTL debugging"), + AST_CLI_DEFINE(handle_cli_show_config, "Show UDPTL config options"), }; -static void __ast_udptl_reload(int reload) +static void udptl_config_destructor(void *obj) +{ + struct udptl_config *cfg = obj; + ao2_cleanup(cfg->general); +} + +static void *udptl_snapshot_alloc(void) { - struct ast_config *cfg; - const char *s; - struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + struct udptl_config *cfg; - cfg = ast_config_load2("udptl.conf", "udptl", config_flags); - if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) { - return; + if (!(cfg = ao2_alloc(sizeof(*cfg), udptl_config_destructor))) { + return NULL; + } + if (!(cfg->general = ao2_alloc(sizeof(*cfg->general), NULL))) { + ao2_ref(cfg, -1); + return NULL; } - udptlstart = DEFAULT_UDPTLSTART; - udptlend = DEFAULT_UDPTLEND; - udptlfecentries = 0; - udptlfecspan = 0; - use_even_ports = 0; + return cfg; +} - if (cfg) { - if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) { - udptlstart = atoi(s); - if (udptlstart < 1024) { - ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n"); - udptlstart = 1024; - } - if (udptlstart > 65535) { - ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n"); - udptlstart = 65535; - } - } - if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) { - udptlend = atoi(s); - if (udptlend < 1024) { - ast_log(LOG_WARNING, "Ports under 1024 are not allowed for T.38.\n"); - udptlend = 1024; - } - if (udptlend > 65535) { - ast_log(LOG_WARNING, "Ports over 65535 are invalid.\n"); - udptlend = 65535; - } - } - if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) { -#ifdef SO_NO_CHECK - if (ast_false(s)) - nochecksums = 1; - else - nochecksums = 0; -#else - if (ast_false(s)) - ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n"); -#endif - } - if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) { - ast_log(LOG_WARNING, "T38FaxUdpEC in udptl.conf is no longer supported; use the t38pt_udptl configuration option in sip.conf instead.\n"); - } - if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) { - ast_log(LOG_WARNING, "T38FaxMaxDatagram in udptl.conf is no longer supported; value is now supplied by T.38 applications.\n"); - } - if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECEntries"))) { - udptlfecentries = atoi(s); - if (udptlfecentries < 1) { - ast_log(LOG_WARNING, "Too small UDPTLFECEntries value. Defaulting to 1.\n"); - udptlfecentries = 1; - } - if (udptlfecentries > MAX_FEC_ENTRIES) { - ast_log(LOG_WARNING, "Too large UDPTLFECEntries value. Defaulting to %d.\n", MAX_FEC_ENTRIES); - udptlfecentries = MAX_FEC_ENTRIES; - } - } - if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECSpan"))) { - udptlfecspan = atoi(s); - if (udptlfecspan < 1) { - ast_log(LOG_WARNING, "Too small UDPTLFECSpan value. Defaulting to 1.\n"); - udptlfecspan = 1; - } - if (udptlfecspan > MAX_FEC_SPAN) { - ast_log(LOG_WARNING, "Too large UDPTLFECSpan value. Defaulting to %d.\n", MAX_FEC_SPAN); - udptlfecspan = MAX_FEC_SPAN; - } - } - if ((s = ast_variable_retrieve(cfg, "general", "use_even_ports"))) { - use_even_ports = ast_true(s); - } - ast_config_destroy(cfg); +static int removed_options_handler(const struct aco_option *opt, struct ast_variable *var, void *obj) +{ + if (!strcasecmp(var->name, "t38faxudpec")) { + ast_log(LOG_WARNING, "t38faxudpec in udptl.conf is no longer supported; use the t38pt_udptl configuration option in sip.conf instead.\n"); + } else if (!strcasecmp(var->name, "t38faxmaxdatagram")) { + ast_log(LOG_WARNING, "t38faxmaxdatagram in udptl.conf is no longer supported; value is now supplied by T.38 applications.\n"); + } + return 0; +} + +static void __ast_udptl_reload(int reload) +{ + if (aco_process_config(&cfg_info, reload)) { + ast_log(LOG_WARNING, "Could not reload udptl config\n"); + } +} + +static int udptl_pre_apply_config(void) { + struct udptl_config *cfg = aco_pending_config(&cfg_info); + + if (!cfg->general) { + return -1; } - if (use_even_ports && (udptlstart & 1)) { - ++udptlstart; - ast_log(LOG_NOTICE, "Odd numbered udptlstart specified but use_even_ports enabled. udptlstart is now %d\n", udptlstart); + +#ifndef SO_NO_CHECK + if (cfg->general->nochecksums) { + ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n"); + cfg->general->nochecksums = 0; + } +#endif + + /* Fix up any global config values that we can handle before replacing the config */ + if (cfg->general->use_even_ports && (cfg->general->start & 1)) { + ++cfg->general->start; + ast_log(LOG_NOTICE, "Odd numbered udptlstart specified but use_even_ports enabled. udptlstart is now %d\n", cfg->general->start); } - if (udptlstart > udptlend) { - ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end ports; defaulting to %d-%d.\n", DEFAULT_UDPTLSTART, DEFAULT_UDPTLEND); - udptlstart = DEFAULT_UDPTLSTART; - udptlend = DEFAULT_UDPTLEND; + if (cfg->general->start > cfg->general->end) { + ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end ports; defaulting to %s-%s.\n", __stringify(DEFAULT_UDPTLSTART), __stringify(DEFAULT_UDPTLEND)); + cfg->general->start = DEFAULT_UDPTLSTART; + cfg->general->end = DEFAULT_UDPTLEND; } - if (use_even_ports && (udptlend & 1)) { - --udptlend; - ast_log(LOG_NOTICE, "Odd numbered udptlend specified but use_even_ports enabled. udptlend is now %d\n", udptlend); + if (cfg->general->use_even_ports && (cfg->general->end & 1)) { + --cfg->general->end; + ast_log(LOG_NOTICE, "Odd numbered udptlend specified but use_even_ports enabled. udptlend is now %d\n", cfg->general->end); } - ast_verb(2, "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend); + + return 0; } int ast_udptl_reload(void) @@ -1416,6 +1456,36 @@ int ast_udptl_reload(void) void ast_udptl_init(void) { + if (aco_info_init(&cfg_info)) { + return; + } + + aco_option_register(&cfg_info, "udptlstart", ACO_EXACT, general_options, __stringify(DEFAULT_UDPTLSTART), + OPT_UINT_T, PARSE_IN_RANGE | PARSE_DEFAULT, + FLDSET(struct udptl_global_options, start), DEFAULT_UDPTLSTART, 1024, 65535); + + aco_option_register(&cfg_info, "udptlend", ACO_EXACT, general_options, __stringify(DEFAULT_UDPTLEND), + OPT_UINT_T, PARSE_IN_RANGE | PARSE_DEFAULT, + FLDSET(struct udptl_global_options, end), DEFAULT_UDPTLEND, 1024, 65535); + + aco_option_register(&cfg_info, "udptlfecentries", ACO_EXACT, general_options, NULL, + OPT_UINT_T, PARSE_IN_RANGE | PARSE_RANGE_DEFAULTS, + FLDSET(struct udptl_global_options, fecentries), 1, MAX_FEC_ENTRIES); + + aco_option_register(&cfg_info, "udptlfecspan", ACO_EXACT, general_options, NULL, + OPT_UINT_T, PARSE_IN_RANGE | PARSE_RANGE_DEFAULTS, + FLDSET(struct udptl_global_options, fecspan), 1, MAX_FEC_SPAN); + + aco_option_register(&cfg_info, "udptlchecksums", ACO_EXACT, general_options, "yes", + OPT_BOOL_T, 0, FLDSET(struct udptl_global_options, nochecksums)); + + aco_option_register(&cfg_info, "use_even_ports", ACO_EXACT, general_options, "no", + OPT_BOOL_T, 1, FLDSET(struct udptl_global_options, use_even_ports)); + + aco_option_register_custom(&cfg_info, "t38faxudpec", ACO_EXACT, general_options, NULL, removed_options_handler, 0); + aco_option_register_custom(&cfg_info, "t38faxmaxdatagram", ACO_EXACT, general_options, NULL, removed_options_handler, 0); + ast_cli_register_multiple(cli_udptl, ARRAY_LEN(cli_udptl)); + __ast_udptl_reload(0); } |