From: Mark Michelson Date: Thu, 9 Feb 2012 16:56:34 +0000 (+0000) Subject: Adding reload support to res_fax.so X-Git-Tag: 1.8.11.0-rc1~55 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aeadbab220f131f11dbd0e05aca5d2a94ad5babb;p=thirdparty%2Fasterisk.git Adding reload support to res_fax.so (closes issue ASTERISK-16712) reported by Frank DiGennaro Review: https://reviewboard.asterisk.org/r/1713 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@354545 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/CHANGES b/CHANGES index d5761cdacf..318b5bf234 100644 --- a/CHANGES +++ b/CHANGES @@ -30,6 +30,10 @@ RTP changes mode has successfully exited. These changes are based on how pjmedia handles media sources and source changes. +FAX changes +------------ + * res_fax now has module reload support. + ------------------------------------------------------------------------------ --- Functionality changes since Asterisk 1.8.7.1 ----------------------------- ------------------------------------------------------------------------------ diff --git a/res/res_fax.c b/res/res_fax.c index 0cc7e3bf85..2c6431f477 100644 --- a/res/res_fax.c +++ b/res/res_fax.c @@ -249,13 +249,28 @@ static AST_RWLIST_HEAD_STATIC(faxmodules, fax_module); #define RES_FAX_STATUSEVENTS 0 #define RES_FAX_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29) -static struct { +struct fax_options { enum ast_fax_modems modems; uint32_t statusevents:1; uint32_t ecm:1; unsigned int minrate; unsigned int maxrate; -} general_options; +}; + +static struct fax_options general_options; + +static const struct fax_options default_options = { + .minrate = RES_FAX_MINRATE, + .maxrate = RES_FAX_MAXRATE, + .statusevents = RES_FAX_STATUSEVENTS, + .modems = RES_FAX_MODEM, + .ecm = AST_FAX_OPTFLAG_TRUE, +}; + +AST_RWLOCK_DEFINE_STATIC(options_lock); + +static void get_general_options(struct fax_options* options); +static void set_general_options(const struct fax_options* options); static const char *config = "res_fax.conf"; @@ -368,6 +383,7 @@ static void destroy_session_details(void *details) static struct ast_fax_session_details *session_details_new(void) { struct ast_fax_session_details *d; + struct fax_options options; if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) { return NULL; @@ -378,6 +394,8 @@ static struct ast_fax_session_details *session_details_new(void) return NULL; } + get_general_options(&options); + AST_LIST_HEAD_INIT_NOLOCK(&d->documents); /* These options need to be set to the configured default and may be overridden by @@ -385,11 +403,11 @@ static struct ast_fax_session_details *session_details_new(void) d->option.request_t38 = AST_FAX_OPTFLAG_FALSE; d->option.send_cng = AST_FAX_OPTFLAG_FALSE; d->option.send_ced = AST_FAX_OPTFLAG_FALSE; - d->option.ecm = general_options.ecm; - d->option.statusevents = general_options.statusevents; - d->modems = general_options.modems; - d->minrate = general_options.minrate; - d->maxrate = general_options.maxrate; + d->option.ecm = options.ecm; + d->option.statusevents = options.statusevents; + d->modems = options.modems; + d->minrate = options.minrate; + d->maxrate = options.maxrate; return d; } @@ -425,12 +443,18 @@ static struct ast_fax_session_details *find_or_create_details(struct ast_channel unsigned int ast_fax_maxrate(void) { - return general_options.maxrate; + struct fax_options options; + get_general_options(&options); + + return options.maxrate; } unsigned int ast_fax_minrate(void) { - return general_options.minrate; + struct fax_options options; + get_general_options(&options); + + return options.minrate; } static int update_modem_bits(enum ast_fax_modems *bits, const char *value) @@ -2428,6 +2452,7 @@ static char *cli_fax_show_settings(struct ast_cli_entry *e, int cmd, struct ast_ { struct fax_module *fax; char modems[128] = ""; + struct fax_options options; switch (cmd) { case CLI_INIT: @@ -2440,12 +2465,14 @@ static char *cli_fax_show_settings(struct ast_cli_entry *e, int cmd, struct ast_ return NULL; } + get_general_options(&options); + ast_cli(a->fd, "FAX For Asterisk Settings:\n"); - ast_cli(a->fd, "\tECM: %s\n", general_options.ecm ? "Enabled" : "Disabled"); - ast_cli(a->fd, "\tStatus Events: %s\n", general_options.statusevents ? "On" : "Off"); - ast_cli(a->fd, "\tMinimum Bit Rate: %d\n", general_options.minrate); - ast_cli(a->fd, "\tMaximum Bit Rate: %d\n", general_options.maxrate); - ast_fax_modem_to_str(general_options.modems, modems, sizeof(modems)); + ast_cli(a->fd, "\tECM: %s\n", options.ecm ? "Enabled" : "Disabled"); + ast_cli(a->fd, "\tStatus Events: %s\n", options.statusevents ? "On" : "Off"); + ast_cli(a->fd, "\tMinimum Bit Rate: %d\n", options.minrate); + ast_cli(a->fd, "\tMaximum Bit Rate: %d\n", options.maxrate); + ast_fax_modem_to_str(options.modems, modems, sizeof(modems)); ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems); ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n"); AST_RWLIST_RDLOCK(&faxmodules); @@ -2588,35 +2615,60 @@ static struct ast_cli_entry fax_cli[] = { AST_CLI_DEFINE(cli_fax_show_stats, "Summarize FAX session history"), }; +static void set_general_options(const struct fax_options *options) +{ + ast_rwlock_wrlock(&options_lock); + general_options = *options; + ast_rwlock_unlock(&options_lock); +} + +static void get_general_options(struct fax_options *options) +{ + ast_rwlock_rdlock(&options_lock); + *options = general_options; + ast_rwlock_unlock(&options_lock); +} + /*! \brief configure res_fax */ -static int set_config(const char *config_file) +static int set_config(int reload) { struct ast_config *cfg; struct ast_variable *v; - struct ast_flags config_flags = { 0 }; + struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; char modems[128] = ""; + struct fax_options options; + int res = 0; + + options = default_options; - /* set defaults */ - general_options.minrate = RES_FAX_MINRATE; - general_options.maxrate = RES_FAX_MAXRATE; - general_options.statusevents = RES_FAX_STATUSEVENTS; - general_options.modems = RES_FAX_MODEM; - general_options.ecm = AST_FAX_OPTFLAG_TRUE; + /* When we're not reloading, we have to be certain to set the general options + * to the defaults in case config loading goes wrong at some point. On a reload, + * the general options need to stay the same as what they were prior to the + * reload rather than being reset to the defaults. + */ + if (!reload) { + set_general_options(&options); + } /* read configuration */ - if (!(cfg = ast_config_load2(config_file, "res_fax", config_flags))) { - ast_log(LOG_NOTICE, "Configuration file '%s' not found, using default options.\n", config_file); + if (!(cfg = ast_config_load2(config, "res_fax", config_flags))) { + ast_log(LOG_NOTICE, "Configuration file '%s' not found, %s options.\n", + config, reload ? "not changing" : "using default"); return 0; } if (cfg == CONFIG_STATUS_FILEINVALID) { - ast_log(LOG_NOTICE, "Configuration file '%s' is invalid, using default options.\n", config_file); + ast_log(LOG_NOTICE, "Configuration file '%s' is invalid, %s options.\n", + config, reload ? "not changing" : "using default"); return 0; } if (cfg == CONFIG_STATUS_FILEUNCHANGED) { - ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); - cfg = ast_config_load2(config_file, "res_fax", config_flags); + return 0; + } + + if (reload) { + options = default_options; } /* create configuration */ @@ -2626,49 +2678,54 @@ static int set_config(const char *config_file) if (!strcasecmp(v->name, "minrate")) { ast_debug(3, "reading minrate '%s' from configuration file\n", v->value); if ((rate = fax_rate_str_to_int(v->value)) == 0) { - ast_config_destroy(cfg); - return -1; + res = -1; + goto end; } - general_options.minrate = rate; + options.minrate = rate; } else if (!strcasecmp(v->name, "maxrate")) { ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value); if ((rate = fax_rate_str_to_int(v->value)) == 0) { - ast_config_destroy(cfg); - return -1; + res = -1; + goto end; } - general_options.maxrate = rate; + options.maxrate = rate; } else if (!strcasecmp(v->name, "statusevents")) { ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value); - general_options.statusevents = ast_true(v->value); + options.statusevents = ast_true(v->value); } else if (!strcasecmp(v->name, "ecm")) { ast_debug(3, "reading ecm '%s' from configuration file\n", v->value); - general_options.ecm = ast_true(v->value); + options.ecm = ast_true(v->value); } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) { - general_options.modems = 0; - update_modem_bits(&general_options.modems, v->value); + options.modems = 0; + update_modem_bits(&options.modems, v->value); } } - ast_config_destroy(cfg); - - if (general_options.maxrate < general_options.minrate) { - ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", general_options.maxrate, general_options.minrate); - return -1; + if (options.maxrate < options.minrate) { + ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", options.maxrate, options.minrate); + res = -1; + goto end; } - if (check_modem_rate(general_options.modems, general_options.minrate)) { - ast_fax_modem_to_str(general_options.modems, modems, sizeof(modems)); - ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, general_options.minrate); - return -1; + if (check_modem_rate(options.modems, options.minrate)) { + ast_fax_modem_to_str(options.modems, modems, sizeof(modems)); + ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, options.minrate); + res = -1; + goto end; } - if (check_modem_rate(general_options.modems, general_options.maxrate)) { - ast_fax_modem_to_str(general_options.modems, modems, sizeof(modems)); - ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, general_options.maxrate); - return -1; + if (check_modem_rate(options.modems, options.maxrate)) { + ast_fax_modem_to_str(options.modems, modems, sizeof(modems)); + ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, options.maxrate); + res = -1; + goto end; } - return 0; + set_general_options(&options); + +end: + ast_config_destroy(cfg); + return res; } /*! \brief FAXOPT read function returns the contents of a FAX option */ @@ -2829,7 +2886,7 @@ static int load_module(void) return AST_MODULE_LOAD_DECLINE; } - if (set_config(config) < 0) { + if (set_config(0) < 0) { ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config); ao2_ref(faxregistry.container, -1); return AST_MODULE_LOAD_DECLINE; @@ -2854,9 +2911,16 @@ static int load_module(void) return res; } +static int reload_module(void) +{ + set_config(1); + return 0; +} + AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Generic FAX Applications", .load = load_module, .unload = unload_module, + .reload = reload_module, .load_pri = AST_MODPRI_APP_DEPEND, );