summaryrefslogtreecommitdiff
path: root/main/udptl.c
diff options
context:
space:
mode:
authorTerry Wilson <twilson@digium.com>2012-06-01 16:33:25 +0000
committerTerry Wilson <twilson@digium.com>2012-06-01 16:33:25 +0000
commitd54717c39e62f4cc8b290ac4836c4d4469d87c24 (patch)
tree5a765e82be880f3b8c2407133fbcc15c4b4349d0 /main/udptl.c
parent463f9d729aed1a5ed538aa3deed1a3fed9462111 (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.c288
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);
}