mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-09 03:18:30 +00:00
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
This commit is contained in:
4
CHANGES
4
CHANGES
@@ -30,6 +30,10 @@ RTP changes
|
|||||||
mode has successfully exited. These changes are based on how pjmedia handles
|
mode has successfully exited. These changes are based on how pjmedia handles
|
||||||
media sources and source changes.
|
media sources and source changes.
|
||||||
|
|
||||||
|
FAX changes
|
||||||
|
------------
|
||||||
|
* res_fax now has module reload support.
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
--- Functionality changes since Asterisk 1.8.7.1 -----------------------------
|
--- Functionality changes since Asterisk 1.8.7.1 -----------------------------
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|||||||
178
res/res_fax.c
178
res/res_fax.c
@@ -249,13 +249,28 @@ static AST_RWLIST_HEAD_STATIC(faxmodules, fax_module);
|
|||||||
#define RES_FAX_STATUSEVENTS 0
|
#define RES_FAX_STATUSEVENTS 0
|
||||||
#define RES_FAX_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29)
|
#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;
|
enum ast_fax_modems modems;
|
||||||
uint32_t statusevents:1;
|
uint32_t statusevents:1;
|
||||||
uint32_t ecm:1;
|
uint32_t ecm:1;
|
||||||
unsigned int minrate;
|
unsigned int minrate;
|
||||||
unsigned int maxrate;
|
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";
|
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)
|
static struct ast_fax_session_details *session_details_new(void)
|
||||||
{
|
{
|
||||||
struct ast_fax_session_details *d;
|
struct ast_fax_session_details *d;
|
||||||
|
struct fax_options options;
|
||||||
|
|
||||||
if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
|
if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -378,6 +394,8 @@ static struct ast_fax_session_details *session_details_new(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_general_options(&options);
|
||||||
|
|
||||||
AST_LIST_HEAD_INIT_NOLOCK(&d->documents);
|
AST_LIST_HEAD_INIT_NOLOCK(&d->documents);
|
||||||
|
|
||||||
/* These options need to be set to the configured default and may be overridden by
|
/* 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.request_t38 = AST_FAX_OPTFLAG_FALSE;
|
||||||
d->option.send_cng = AST_FAX_OPTFLAG_FALSE;
|
d->option.send_cng = AST_FAX_OPTFLAG_FALSE;
|
||||||
d->option.send_ced = AST_FAX_OPTFLAG_FALSE;
|
d->option.send_ced = AST_FAX_OPTFLAG_FALSE;
|
||||||
d->option.ecm = general_options.ecm;
|
d->option.ecm = options.ecm;
|
||||||
d->option.statusevents = general_options.statusevents;
|
d->option.statusevents = options.statusevents;
|
||||||
d->modems = general_options.modems;
|
d->modems = options.modems;
|
||||||
d->minrate = general_options.minrate;
|
d->minrate = options.minrate;
|
||||||
d->maxrate = general_options.maxrate;
|
d->maxrate = options.maxrate;
|
||||||
|
|
||||||
return d;
|
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)
|
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)
|
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)
|
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;
|
struct fax_module *fax;
|
||||||
char modems[128] = "";
|
char modems[128] = "";
|
||||||
|
struct fax_options options;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case CLI_INIT:
|
case CLI_INIT:
|
||||||
@@ -2440,12 +2465,14 @@ static char *cli_fax_show_settings(struct ast_cli_entry *e, int cmd, struct ast_
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_general_options(&options);
|
||||||
|
|
||||||
ast_cli(a->fd, "FAX For Asterisk Settings:\n");
|
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, "\tECM: %s\n", options.ecm ? "Enabled" : "Disabled");
|
||||||
ast_cli(a->fd, "\tStatus Events: %s\n", general_options.statusevents ? "On" : "Off");
|
ast_cli(a->fd, "\tStatus Events: %s\n", options.statusevents ? "On" : "Off");
|
||||||
ast_cli(a->fd, "\tMinimum Bit Rate: %d\n", general_options.minrate);
|
ast_cli(a->fd, "\tMinimum Bit Rate: %d\n", options.minrate);
|
||||||
ast_cli(a->fd, "\tMaximum Bit Rate: %d\n", general_options.maxrate);
|
ast_cli(a->fd, "\tMaximum Bit Rate: %d\n", options.maxrate);
|
||||||
ast_fax_modem_to_str(general_options.modems, modems, sizeof(modems));
|
ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
|
||||||
ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems);
|
ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems);
|
||||||
ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n");
|
ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n");
|
||||||
AST_RWLIST_RDLOCK(&faxmodules);
|
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"),
|
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 */
|
/*! \brief configure res_fax */
|
||||||
static int set_config(const char *config_file)
|
static int set_config(int reload)
|
||||||
{
|
{
|
||||||
struct ast_config *cfg;
|
struct ast_config *cfg;
|
||||||
struct ast_variable *v;
|
struct ast_variable *v;
|
||||||
struct ast_flags config_flags = { 0 };
|
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
|
||||||
char modems[128] = "";
|
char modems[128] = "";
|
||||||
|
struct fax_options options;
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
/* set defaults */
|
options = default_options;
|
||||||
general_options.minrate = RES_FAX_MINRATE;
|
|
||||||
general_options.maxrate = RES_FAX_MAXRATE;
|
/* When we're not reloading, we have to be certain to set the general options
|
||||||
general_options.statusevents = RES_FAX_STATUSEVENTS;
|
* to the defaults in case config loading goes wrong at some point. On a reload,
|
||||||
general_options.modems = RES_FAX_MODEM;
|
* the general options need to stay the same as what they were prior to the
|
||||||
general_options.ecm = AST_FAX_OPTFLAG_TRUE;
|
* reload rather than being reset to the defaults.
|
||||||
|
*/
|
||||||
|
if (!reload) {
|
||||||
|
set_general_options(&options);
|
||||||
|
}
|
||||||
|
|
||||||
/* read configuration */
|
/* read configuration */
|
||||||
if (!(cfg = ast_config_load2(config_file, "res_fax", config_flags))) {
|
if (!(cfg = ast_config_load2(config, "res_fax", config_flags))) {
|
||||||
ast_log(LOG_NOTICE, "Configuration file '%s' not found, using default options.\n", config_file);
|
ast_log(LOG_NOTICE, "Configuration file '%s' not found, %s options.\n",
|
||||||
|
config, reload ? "not changing" : "using default");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg == CONFIG_STATUS_FILEINVALID) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
|
if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
|
||||||
ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
|
return 0;
|
||||||
cfg = ast_config_load2(config_file, "res_fax", config_flags);
|
}
|
||||||
|
|
||||||
|
if (reload) {
|
||||||
|
options = default_options;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create configuration */
|
/* create configuration */
|
||||||
@@ -2626,49 +2678,54 @@ static int set_config(const char *config_file)
|
|||||||
if (!strcasecmp(v->name, "minrate")) {
|
if (!strcasecmp(v->name, "minrate")) {
|
||||||
ast_debug(3, "reading minrate '%s' from configuration file\n", v->value);
|
ast_debug(3, "reading minrate '%s' from configuration file\n", v->value);
|
||||||
if ((rate = fax_rate_str_to_int(v->value)) == 0) {
|
if ((rate = fax_rate_str_to_int(v->value)) == 0) {
|
||||||
ast_config_destroy(cfg);
|
res = -1;
|
||||||
return -1;
|
goto end;
|
||||||
}
|
}
|
||||||
general_options.minrate = rate;
|
options.minrate = rate;
|
||||||
} else if (!strcasecmp(v->name, "maxrate")) {
|
} else if (!strcasecmp(v->name, "maxrate")) {
|
||||||
ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value);
|
ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value);
|
||||||
if ((rate = fax_rate_str_to_int(v->value)) == 0) {
|
if ((rate = fax_rate_str_to_int(v->value)) == 0) {
|
||||||
ast_config_destroy(cfg);
|
res = -1;
|
||||||
return -1;
|
goto end;
|
||||||
}
|
}
|
||||||
general_options.maxrate = rate;
|
options.maxrate = rate;
|
||||||
} else if (!strcasecmp(v->name, "statusevents")) {
|
} else if (!strcasecmp(v->name, "statusevents")) {
|
||||||
ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value);
|
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")) {
|
} else if (!strcasecmp(v->name, "ecm")) {
|
||||||
ast_debug(3, "reading ecm '%s' from configuration file\n", v->value);
|
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"))) {
|
} else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) {
|
||||||
general_options.modems = 0;
|
options.modems = 0;
|
||||||
update_modem_bits(&general_options.modems, v->value);
|
update_modem_bits(&options.modems, v->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(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(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_general_options(&options);
|
||||||
|
|
||||||
|
end:
|
||||||
ast_config_destroy(cfg);
|
ast_config_destroy(cfg);
|
||||||
|
return res;
|
||||||
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 (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(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief FAXOPT read function returns the contents of a FAX option */
|
/*! \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;
|
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);
|
ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config);
|
||||||
ao2_ref(faxregistry.container, -1);
|
ao2_ref(faxregistry.container, -1);
|
||||||
return AST_MODULE_LOAD_DECLINE;
|
return AST_MODULE_LOAD_DECLINE;
|
||||||
@@ -2854,9 +2911,16 @@ static int load_module(void)
|
|||||||
return res;
|
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",
|
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Generic FAX Applications",
|
||||||
.load = load_module,
|
.load = load_module,
|
||||||
.unload = unload_module,
|
.unload = unload_module,
|
||||||
|
.reload = reload_module,
|
||||||
.load_pri = AST_MODPRI_APP_DEPEND,
|
.load_pri = AST_MODPRI_APP_DEPEND,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user