From 1fc76768a99f651fccb359a836928fec4a6615a4 Mon Sep 17 00:00:00 2001 From: transnexus Date: Tue, 10 Aug 2010 07:26:17 +0000 Subject: Fixed the issue caused by EXTEN including user parameters. git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.8@281497 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_osplookup.c | 8 ++- channels/chan_local.c | 32 ++++++++++++ channels/chan_mgcp.c | 2 +- channels/chan_sip.c | 5 +- configs/cdr.conf.sample | 31 ++++++------ configs/sip.conf.sample | 2 + include/asterisk/pbx.h | 8 --- main/cdr.c | 39 ++++++++++----- main/pbx.c | 31 +++--------- main/utils.c | 16 +++++- res/res_fax.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++-- 11 files changed, 234 insertions(+), 68 deletions(-) diff --git a/apps/app_osplookup.c b/apps/app_osplookup.c index ea20cee77..239d6d501 100644 --- a/apps/app_osplookup.c +++ b/apps/app_osplookup.c @@ -1493,6 +1493,7 @@ static int osp_lookup( char callingnum[OSP_SIZE_NORSTR]; char callednum[OSP_SIZE_NORSTR]; char destination[OSP_SIZE_NORSTR]; + char* tmp; unsigned int tokenlen; char token[OSP_SIZE_TOKSTR]; char src[OSP_SIZE_NORSTR]; @@ -1565,6 +1566,11 @@ static int osp_lookup( } } + ast_copy_string(callednum, called, sizeof(callednum)); + if((tmp = strchr(callednum, ';')) != NULL) { + *tmp = '\0'; + } + callidnum = 0; callids[0] = NULL; for (i = 0; i < OSP_CALLID_MAXNUM; i++) { @@ -1605,7 +1611,7 @@ static int osp_lookup( dev, calling ? calling : "", OSPC_NFORMAT_E164, - called, + callednum, OSPC_NFORMAT_E164, NULL, callidnum, diff --git a/channels/chan_local.c b/channels/chan_local.c index d1f66f8dd..aebca441a 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -409,6 +409,38 @@ static void check_bridge(struct local_pvt *p) p->chan->audiohooks = p->owner->audiohooks; p->owner->audiohooks = audiohooks_swapper; } + + /* If any Caller ID was set, preserve it after masquerade like above. We must check + * to see if Caller ID was set because otherwise we'll mistakingly copy info not + * set from the dialplan and will overwrite the real channel Caller ID. The reason + * for this whole preswapping action is because the Caller ID is set on the channel + * thread (which is the to be masqueraded away local channel) before both local + * channels are optimized away. + */ + if (p->owner->caller.id.name.valid || p->owner->caller.id.number.valid + || p->owner->caller.id.subaddress.valid || p->owner->caller.ani.name.valid + || p->owner->caller.ani.number.valid || p->owner->caller.ani.subaddress.valid) { + struct ast_party_caller tmp; + tmp = p->owner->caller; + p->owner->caller = p->chan->_bridge->caller; + p->chan->_bridge->caller = tmp; + } + if (p->owner->redirecting.from.name.valid || p->owner->redirecting.from.number.valid + || p->owner->redirecting.from.subaddress.valid || p->owner->redirecting.to.name.valid + || p->owner->redirecting.to.number.valid || p->owner->redirecting.to.subaddress.valid) { + struct ast_party_redirecting tmp; + tmp = p->owner->redirecting; + p->owner->redirecting = p->chan->_bridge->redirecting; + p->chan->_bridge->redirecting = tmp; + } + if (p->owner->dialed.number.str || p->owner->dialed.subaddress.valid) { + struct ast_party_dialed tmp; + tmp = p->owner->dialed; + p->owner->dialed = p->chan->_bridge->dialed; + p->chan->_bridge->dialed = tmp; + } + + ast_app_group_update(p->chan, p->owner); ast_channel_masquerade(p->owner, p->chan->_bridge); ast_set_flag(p, LOCAL_ALREADY_MASQED); diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index 485b39aad..a787eab72 100644 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -3580,7 +3580,7 @@ static int find_and_retrans(struct mgcp_subchannel *sub, struct mgcp_request *re if (sscanf(req->identifier, "%30d", &seqno) != 1) { seqno = 0; } - for (cur = sub->parent->parent->responses, next = cur->next; cur; cur = next, next = cur->next) { + for (cur = sub->parent->parent->responses, next = cur ? cur->next : NULL; cur; cur = next, next = cur ? cur->next : NULL) { if (now - cur->whensent > RESPONSE_TIMEOUT) { /* Delete this entry */ if (prev) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 47dc2610d..cdf598a66 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -12652,7 +12652,6 @@ static int expire_register(const void *data) peer->expire = -1; peer->portinuri = 0; - memset(&peer->addr, 0, sizeof(peer->addr)); destroy_association(peer); /* remove registration data from storage */ set_socket_transport(&peer->socket, peer->default_outbound_transport); @@ -12681,6 +12680,10 @@ static int expire_register(const void *data) } } + /* Only clear the addr after we check for destruction. The addr must remain + * in order to unlink from the peers_by_ip container correctly */ + memset(&peer->addr, 0, sizeof(peer->addr)); + unref_peer(peer, "removing peer ref for expire_register"); return 0; diff --git a/configs/cdr.conf.sample b/configs/cdr.conf.sample index 3866ab1fa..b0c38c6cf 100644 --- a/configs/cdr.conf.sample +++ b/configs/cdr.conf.sample @@ -29,6 +29,22 @@ ; channel.) ;unanswered = no +; Normally, CDR's are not closed out until after all extensions are finished +; executing. By enabling this option, the CDR will be ended before executing +; the "h" extension so that CDR values such as "end" and "billsec" may be +; retrieved inside of of this extension. The default value is "no". +;endbeforehexten=no + +; Normally, the 'billsec' field logged to the backends (text files or databases) +; is simply the end time (hangup time) minus the answer time in seconds. Internally, +; asterisk stores the time in terms of microseconds and seconds. By setting +; initiatedseconds to 'yes', you can force asterisk to report any seconds +; that were initiated (a sort of round up method). Technically, this is +; when the microsecond part of the end time is greater than the microsecond +; part of the answer time, then the billsec time is incremented one second. +; The default value is "no". +;initiatedseconds=no + ; Define the CDR batch mode, where instead of posting the CDR at the end of ; every call, the data will be stored in a buffer to help alleviate load on the ; asterisk server. Default is "no". @@ -65,21 +81,6 @@ ; is "yes". ;safeshutdown=yes -; Normally, CDR's are not closed out until after all extensions are finished -; executing. By enabling this option, the CDR will be ended before executing -; the "h" extension so that CDR values such as "end" and "billsec" may be -; retrieved inside of of this extension. -;endbeforehexten=no - -; Normally, the 'billsec' field logged to the backends (text files or databases) -; is simply the end time (hangup time) minus the answer time in seconds. Internally, -; asterisk stores the time in terms of microseconds and seconds. By setting -; initiatedseconds to 'yes', you can force asterisk to report any seconds -; that were initiated (a sort of round up method). Technically, this is -; when the microsecond part of the end time is greater than the microsecond -; part of the answer time, then the billsec time is incremented one second. -;initiatedseconds=no - ; ; ; CHOOSING A CDR "BACKEND" (what kind of output to generate) diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index 01fd29b00..35f4f682e 100644 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -144,6 +144,8 @@ allowoverlap=no ; Disable overlap dialing support. (Default is y ; d) Listen on the IPv4 and IPv6 wildcards. Example: bindaddr=:: ; (You can choose independently for UDP, TCP, and TLS, by specifying different values for ; "udpbindaddr", "tcpbindaddr", and "tlsbindaddr".) +; (Note that using bindaddr=:: will show only a single IPv6 socket in netstat. +; IPv4 is supported at the same time using IPv4-mapped IPv6 addresses.) ; ; You may optionally add a port number. (The default is port 5060 for UDP and TCP, 5061 ; for TLS). diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h index ac09f009b..a0ef3d476 100644 --- a/include/asterisk/pbx.h +++ b/include/asterisk/pbx.h @@ -1220,14 +1220,6 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action); - -/* every time a write lock is obtained for contexts, - a counter is incremented. You can check this via the - following func */ - -int ast_wrlock_contexts_version(void); - - /*! \brief hashtable functions for contexts */ /*! @{ */ int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b); diff --git a/main/cdr.c b/main/cdr.c index a6096976d..c9b58238b 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -84,18 +84,26 @@ static struct sched_context *sched; static int cdr_sched = -1; static pthread_t cdr_thread = AST_PTHREADT_NULL; -#define BATCH_SIZE_DEFAULT 100 -#define BATCH_TIME_DEFAULT 300 -#define BATCH_SCHEDULER_ONLY_DEFAULT 0 -#define BATCH_SAFE_SHUTDOWN_DEFAULT 1 +static int enabled; +static const int ENABLED_DEFAULT = 1; -static int enabled; /*! Is the CDR subsystem enabled ? */ -static int unanswered; static int batchmode; +static const int BATCHMODE_DEFAULT = 0; + +static int unanswered; +static const int UNANSWERED_DEFAULT = 0; + static int batchsize; +static const int BATCH_SIZE_DEFAULT = 100; + static int batchtime; +static const int BATCH_TIME_DEFAULT = 300; + static int batchscheduleronly; +static const int BATCH_SCHEDULER_ONLY_DEFAULT = 0; + static int batchsafeshutdown; +static const int BATCH_SAFE_SHUTDOWN_DEFAULT = 1; AST_MUTEX_DEFINE_STATIC(cdr_batch_lock); @@ -1492,22 +1500,27 @@ static int do_reload(int reload) int res=0; struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; - if ((config = ast_config_load2("cdr.conf", "cdr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) - return 0; - if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEUNCHANGED || config == CONFIG_STATUS_FILEINVALID) { + if ((config = ast_config_load2("cdr.conf", "cdr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { return 0; } ast_mutex_lock(&cdr_batch_lock); + was_enabled = enabled; + was_batchmode = batchmode; + batchsize = BATCH_SIZE_DEFAULT; batchtime = BATCH_TIME_DEFAULT; batchscheduleronly = BATCH_SCHEDULER_ONLY_DEFAULT; batchsafeshutdown = BATCH_SAFE_SHUTDOWN_DEFAULT; - was_enabled = enabled; - was_batchmode = batchmode; - enabled = 1; - batchmode = 0; + enabled = ENABLED_DEFAULT; + batchmode = BATCHMODE_DEFAULT; + unanswered = UNANSWERED_DEFAULT; + + if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) { + ast_mutex_unlock(&cdr_batch_lock); + return 0; + } /* don't run the next scheduled CDR posting while reloading */ AST_SCHED_DEL(sched, cdr_sched); diff --git a/main/pbx.c b/main/pbx.c index 4216b853a..f9476fd1d 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -1164,7 +1164,11 @@ static struct pbx_builtin { static struct ast_context *contexts; static struct ast_hashtab *contexts_table = NULL; -AST_RWLOCK_DEFINE_STATIC(conlock); /*!< Lock for the ast_context list */ +/*!\brief Lock for the ast_context list + * This lock MUST be recursive, or a deadlock on reload may result. See + * https://issues.asterisk.org/view.php?id=17643 + */ +AST_MUTEX_DEFINE_STATIC(conlock); static AST_RWLIST_HEAD_STATIC(apps, ast_app); @@ -7016,7 +7020,6 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_ */ struct timeval begintime, writelocktime, endlocktime, enddeltime; - int wrlock_ver; begintime = ast_tvnow(); ast_rdlock_contexts(); @@ -7025,15 +7028,6 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_ context_merge(extcontexts, exttable, tmp, registrar); } ast_hashtab_end_traversal(iter); - wrlock_ver = ast_wrlock_contexts_version(); - - ast_unlock_contexts(); /* this feels real retarded, but you must do - what you must do If this isn't done, the following - wrlock is a guraranteed deadlock */ - ast_wrlock_contexts(); - if (ast_wrlock_contexts_version() > wrlock_ver+1) { - ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n"); - } AST_RWLIST_WRLOCK(&hints); writelocktime = ast_tvnow(); @@ -9836,32 +9830,23 @@ int load_pbx(void) return 0; } -static int conlock_wrlock_version = 0; - -int ast_wrlock_contexts_version(void) -{ - return conlock_wrlock_version; -} /* * Lock context list functions ... */ int ast_wrlock_contexts() { - int res = ast_rwlock_wrlock(&conlock); - if (!res) - ast_atomic_fetchadd_int(&conlock_wrlock_version, 1); - return res; + return ast_mutex_lock(&conlock); } int ast_rdlock_contexts() { - return ast_rwlock_rdlock(&conlock); + return ast_mutex_lock(&conlock); } int ast_unlock_contexts() { - return ast_rwlock_unlock(&conlock); + return ast_mutex_unlock(&conlock); } /* diff --git a/main/utils.c b/main/utils.c index 5961a7339..6f2c884d0 100644 --- a/main/utils.c +++ b/main/utils.c @@ -1615,7 +1615,8 @@ ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr size_t space = (*pool_head)->size - (*pool_head)->used; size_t to_alloc = needed + sizeof(ast_string_field_allocation); - if (__builtin_expect(to_alloc > space, 0)) { + /* This +1 accounts for alignment on SPARC */ + if (__builtin_expect(to_alloc + 1 > space, 0)) { size_t new_size = (*pool_head)->size; while (new_size < to_alloc) { @@ -1632,6 +1633,13 @@ ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr } result = (*pool_head)->base + (*pool_head)->used; +#ifdef __sparc__ + /* SPARC requires that the allocation field be aligned. */ + if ((long) result % sizeof(ast_string_field_allocation)) { + result++; + (*pool_head)->used++; + } +#endif (*pool_head)->used += to_alloc; (*pool_head)->active += needed; result += sizeof(ast_string_field_allocation); @@ -1706,6 +1714,12 @@ void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr, } } else { target = (*pool_head)->base + (*pool_head)->used + sizeof(ast_string_field_allocation); +#ifdef __sparc__ + if ((long) target % sizeof(ast_string_field_allocation)) { + target++; + space--; + } +#endif available = space - sizeof(ast_string_field_allocation); } diff --git a/res/res_fax.c b/res/res_fax.c index 03fd128a7..3da2d02f8 100644 --- a/res/res_fax.c +++ b/res/res_fax.c @@ -387,9 +387,6 @@ static struct ast_fax_session_details *session_details_new(void) d->modems = general_options.modems; d->minrate = general_options.minrate; d->maxrate = general_options.maxrate; - ast_string_field_set(d, result, "FAILED"); - ast_string_field_set(d, resultstr, "error starting fax session"); - ast_string_field_set(d, error, "INIT_ERROR"); return d; } @@ -500,6 +497,45 @@ static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t buf return 0; } +static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate) +{ + switch (rate) { + case 2400: + if (!(modems & (AST_FAX_MODEM_V27 | AST_FAX_MODEM_V34))) { + return 1; + } + break; + case 4800: + if (!(modems & (AST_FAX_MODEM_V27 | AST_FAX_MODEM_V34))) { + return 1; + } + break; + case 7200: + case 9600: + if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) { + return 1; + } + break; + case 12000: + case 14400: + if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V34))) { + return 1; + } + break; + case 28800: + case 33600: + if (!(modems & AST_FAX_MODEM_V34)) { + return 1; + } + break; + default: + /* this should never happen */ + return 1; + } + + return 0; +} + /*! \brief register a FAX technology module */ int ast_fax_tech_register(struct ast_fax_tech *tech) { @@ -1363,7 +1399,7 @@ static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_ /*! \brief initiate a receive FAX session */ static int receivefax_exec(struct ast_channel *chan, const char *data) { - char *parse; + char *parse, modems[128] = ""; int channel_alive; struct ast_fax_session_details *details; struct ast_fax_document *doc; @@ -1390,8 +1426,40 @@ static int receivefax_exec(struct ast_channel *chan, const char *data) return -1; } + ast_string_field_set(details, result, "FAILED"); + ast_string_field_set(details, resultstr, "error starting fax session"); + ast_string_field_set(details, error, "INIT_ERROR"); set_channel_variables(chan, details); + if (details->maxrate < details->minrate) { + ast_string_field_set(details, error, "INVALID_ARGUMENTS"); + ast_string_field_set(details, resultstr, "maxrate is less than minrate"); + set_channel_variables(chan, details); + ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", details->maxrate, details->minrate); + ao2_ref(details, -1); + return -1; + } + + if (check_modem_rate(details->modems, details->minrate)) { + ast_fax_modem_to_str(details->modems, modems, sizeof(modems)); + ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, details->minrate); + ast_string_field_set(details, error, "INVALID_ARGUMENTS"); + ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings"); + set_channel_variables(chan, details); + ao2_ref(details, -1); + return -1; + } + + if (check_modem_rate(details->modems, details->maxrate)) { + ast_fax_modem_to_str(details->modems, modems, sizeof(modems)); + ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, details->maxrate); + ast_string_field_set(details, error, "INVALID_ARGUMENTS"); + ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings"); + set_channel_variables(chan, details); + ao2_ref(details, -1); + return -1; + } + if (ast_strlen_zero(data)) { ast_string_field_set(details, error, "INVALID_ARGUMENTS"); ast_string_field_set(details, resultstr, "invalid arguments"); @@ -1768,7 +1836,7 @@ static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_det /*! \brief initiate a send FAX session */ static int sendfax_exec(struct ast_channel *chan, const char *data) { - char *parse, *filenames, *c; + char *parse, *filenames, *c, modems[128] = ""; int channel_alive, file_count; struct ast_fax_session_details *details; struct ast_fax_document *doc; @@ -1795,8 +1863,40 @@ static int sendfax_exec(struct ast_channel *chan, const char *data) return -1; } + ast_string_field_set(details, result, "FAILED"); + ast_string_field_set(details, resultstr, "error starting fax session"); + ast_string_field_set(details, error, "INIT_ERROR"); set_channel_variables(chan, details); + if (details->maxrate < details->minrate) { + ast_string_field_set(details, error, "INVALID_ARGUMENTS"); + ast_string_field_set(details, resultstr, "maxrate is less than minrate"); + set_channel_variables(chan, details); + ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", details->maxrate, details->minrate); + ao2_ref(details, -1); + return -1; + } + + if (check_modem_rate(details->modems, details->minrate)) { + ast_fax_modem_to_str(details->modems, modems, sizeof(modems)); + ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, details->minrate); + ast_string_field_set(details, error, "INVALID_ARGUMENTS"); + ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings"); + set_channel_variables(chan, details); + ao2_ref(details, -1); + return -1; + } + + if (check_modem_rate(details->modems, details->maxrate)) { + ast_fax_modem_to_str(details->modems, modems, sizeof(modems)); + ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, details->maxrate); + ast_string_field_set(details, error, "INVALID_ARGUMENTS"); + ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings"); + set_channel_variables(chan, details); + ao2_ref(details, -1); + return -1; + } + if (ast_strlen_zero(data)) { ast_string_field_set(details, error, "INVALID_ARGUMENTS"); ast_string_field_set(details, resultstr, "invalid arguments"); @@ -2292,6 +2392,7 @@ static int set_config(const char *config_file) struct ast_config *cfg; struct ast_variable *v; struct ast_flags config_flags = { 0 }; + char modems[128] = ""; /* set defaults */ general_options.minrate = RES_FAX_MINRATE; @@ -2342,6 +2443,23 @@ static int set_config(const char *config_file) 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 (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; } -- cgit v1.2.3