diff options
author | rmudgett <rmudgett@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-08-20 16:46:22 +0000 |
---|---|---|
committer | rmudgett <rmudgett@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-08-20 16:46:22 +0000 |
commit | 66bd24a0507255b9575b74ae12acf7bf575bba9d (patch) | |
tree | 8c21c17634f92b3a5d073d07e3bb02ea16881c70 | |
parent | 994debde3c3d78011509a53fc68dd6ae27a6024e (diff) |
Merged revision 278274 from
https://origsvn.digium.com/svn/asterisk/trunk
..........
r278274 | rmudgett | 2010-07-20 17:38:13 -0500 (Tue, 20 Jul 2010) | 1 line
Reference correct struct member for unlikely event PRI_EVENT_CONFIG_ERR.
..........
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@283123 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | apps/app_dial.c | 3 | ||||
-rw-r--r-- | channels/chan_dahdi.c | 4 | ||||
-rw-r--r-- | channels/chan_local.c | 20 | ||||
-rw-r--r-- | channels/chan_sip.c | 140 | ||||
-rw-r--r-- | configs/say.conf.sample | 96 | ||||
-rw-r--r-- | configs/sip.conf.sample | 13 | ||||
-rwxr-xr-x | contrib/scripts/astcli | 167 | ||||
-rw-r--r-- | main/channel.c | 14 | ||||
-rw-r--r-- | main/pbx.c | 14 | ||||
-rw-r--r-- | pbx/pbx_config.c | 7 |
10 files changed, 439 insertions, 39 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c index 3a942ffc2..f1dd6ef3d 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -1856,8 +1856,9 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags sentringing = 0; ast_indicate(chan, -1); } - /* Be sure no generators are left on it */ + /* Be sure no generators are left on it and reset the visible indication */ ast_deactivate_generator(chan); + chan->visible_indication = 0; /* Make sure channels are compatible */ res = ast_channel_make_compatible(chan, peer); if (res < 0) { diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index a4e549a6f..667ee0313 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -5636,7 +5636,7 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); #ifdef HAVE_PRI p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ - if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { + if (!p->progress && !p->alerting && p->sig==SIG_PRI && p->pri && !p->outgoing) { if (p->pri->pri) { if (!pri_grab(p, p->pri)) { pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); @@ -10066,7 +10066,7 @@ static void *pri_dchannel(void *vpri) } break; case PRI_EVENT_CONFIG_ERR: - ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); + ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err); break; case PRI_EVENT_RESTART_ACK: chanpos = pri_find_principle(pri, e->restartack.channel); diff --git a/channels/chan_local.c b/channels/chan_local.c index 81f16eadf..7fa6968cc 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -294,6 +294,26 @@ 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->cid.cid_dnid || p->owner->cid.cid_num || + p->owner->cid.cid_name || p->owner->cid.cid_ani || + p->owner->cid.cid_rdnis || p->owner->cid.cid_pres || + p->owner->cid.cid_ani2 || p->owner->cid.cid_ton || + p->owner->cid.cid_tns) { + + struct ast_callerid tmpcid; + tmpcid = p->owner->cid; + p->owner->cid = p->chan->_bridge->cid; + p->chan->_bridge->cid = tmpcid; + } + 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_sip.c b/channels/chan_sip.c index 631da359d..a7edd8a25 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -149,6 +149,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/compiler.h" #include "asterisk/threadstorage.h" #include "asterisk/translate.h" +#include "asterisk/astobj2.h" #ifndef FALSE #define FALSE 0 @@ -855,6 +856,12 @@ static int global_t38_capability = T38FAX_VERSION_0 | T38FAX_RATE_2400 | T38FAX_ #define sipdebug_config ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_CONFIG) #define sipdebug_console ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_CONSOLE) +/*! \brief provisional keep alive scheduler item data */ +struct provisional_keepalive_data { + struct sip_pvt *pvt; + int sched_id; +}; + /*! \brief T38 States for a call */ enum t38state { T38_DISABLED = 0, /*!< Not enabled */ @@ -1044,7 +1051,7 @@ static struct sip_pvt { struct ast_variable *chanvars; /*!< Channel variables to set for inbound call */ AST_LIST_HEAD_NOLOCK(request_queue, sip_request) request_queue; /*!< Requests that arrived but could not be processed immediately */ int request_queue_sched_id; /*!< Scheduler ID of any scheduled action to process queued requests */ - int provisional_keepalive_sched_id; /*!< Scheduler ID for provisional responses that need to be sent out to avoid cancellation */ + struct provisional_keepalive_data *provisional_keepalive_data; /*!< Scheduler data for provisional responses that need to be sent out to avoid cancellation */ const char *last_provisional; /*!< The last successfully transmitted provisonal response message */ struct sip_pvt *next; /*!< Next dialog in chain */ struct sip_invite_param *options; /*!< Options for INVITE */ @@ -2335,44 +2342,124 @@ static void add_blank(struct sip_request *req) } } -static int send_provisional_keepalive_full(struct sip_pvt *pvt, int with_sdp) +/*! \brief This is called by the scheduler to resend the last provisional message in a dialog */ +static int send_provisional_keepalive_full(struct provisional_keepalive_data *data, int with_sdp) { const char *msg = NULL; + int res = 0; + struct sip_pvt *pvt = data->pvt; - if (!pvt->last_provisional || !strncasecmp(pvt->last_provisional, "100", 3)) { - msg = "183 Session Progress"; + if (!pvt) { + ao2_ref(data, -1); /* not rescheduling so drop ref. in this case the dialog has already dropped this ref */ + return res; } - if (pvt->invitestate < INV_COMPLETED) { - if (with_sdp) { - transmit_response_with_sdp(pvt, S_OR(msg, pvt->last_provisional), &pvt->initreq, XMIT_UNRELIABLE); + ast_mutex_lock(&pvt->lock); + while (pvt->owner && ast_channel_trylock(pvt->owner)) { + ast_mutex_unlock(&pvt->lock); + sched_yield(); + if ((pvt = data->pvt)) { + ast_mutex_lock(&pvt->lock); } else { - transmit_response(pvt, S_OR(msg, pvt->last_provisional), &pvt->initreq); + ao2_ref(data, -1); + return res; } - return PROVIS_KEEPALIVE_TIMEOUT; } - return 0; + if (data->sched_id == -1 || pvt->invitestate >= INV_COMPLETED) { + goto provisional_keepalive_cleanup; + } + + if (!pvt->last_provisional || !strncasecmp(pvt->last_provisional, "100", 3)) { + msg = "183 Session Progress"; + } + + if (with_sdp) { + transmit_response_with_sdp(pvt, S_OR(msg, pvt->last_provisional), &pvt->initreq, XMIT_UNRELIABLE); + } else { + transmit_response(pvt, S_OR(msg, pvt->last_provisional), &pvt->initreq); + } + + res = PROVIS_KEEPALIVE_TIMEOUT; /* reschedule the keepalive event */ + +provisional_keepalive_cleanup: + if (!res) { /* not rescheduling, so drop ref */ + data->sched_id = -1; /* if we don't re-schedule, make sure to remove the sched id */ + ao2_ref(data, -1); /* release the scheduler's reference to this data */ + } + + if (pvt->owner) { + ast_channel_unlock(pvt->owner); + } + ast_mutex_unlock(&pvt->lock); + + return res; } -static int send_provisional_keepalive(const void *data) { - struct sip_pvt *pvt = (struct sip_pvt *) data; +static int send_provisional_keepalive(const void *data) +{ + struct provisional_keepalive_data *d = (struct provisional_keepalive_data *) data; - return send_provisional_keepalive_full(pvt, 0); + return send_provisional_keepalive_full(d, 0); } -static int send_provisional_keepalive_with_sdp(const void *data) { - struct sip_pvt *pvt = (void *)data; +static int send_provisional_keepalive_with_sdp(const void *data) +{ + struct provisional_keepalive_data *d = (struct provisional_keepalive_data *) data; + + return send_provisional_keepalive_full(d, 1); +} + +static void *unref_provisional_keepalive(struct provisional_keepalive_data *data) +{ + if (data) { + data->sched_id = -1; + data->pvt = NULL; + ao2_ref(data, -1); + } + return NULL; +} - return send_provisional_keepalive_full(pvt, 1); +static void remove_provisional_keepalive_sched(struct sip_pvt *pvt) +{ + int res; + if (!pvt->provisional_keepalive_data) { + return; + } + res = AST_SCHED_DEL(sched, pvt->provisional_keepalive_data->sched_id); + /* If we could not remove this item. remove pvt's reference this data and mark it for removal + * for the next time the scheduler uses it. The scheduler has it's own ref to this data + * and will detect it should not reschedule the event since the sched_id is -1 and pvt == NULL */ + if (res == -1) { + pvt->provisional_keepalive_data = unref_provisional_keepalive(pvt->provisional_keepalive_data); + } } static void update_provisional_keepalive(struct sip_pvt *pvt, int with_sdp) { - AST_SCHED_DEL(sched, pvt->provisional_keepalive_sched_id); + remove_provisional_keepalive_sched(pvt); + + if (!pvt->provisional_keepalive_data) { + if (!(pvt->provisional_keepalive_data = ao2_alloc(sizeof(*pvt->provisional_keepalive_data), NULL))) { + return; /* alloc error, can not recover */ + } + pvt->provisional_keepalive_data->sched_id = -1; + pvt->provisional_keepalive_data->pvt = pvt; + } + + /* give the scheduler a ref */ + ao2_ref(pvt->provisional_keepalive_data, +1); - pvt->provisional_keepalive_sched_id = ast_sched_add(sched, PROVIS_KEEPALIVE_TIMEOUT, - with_sdp ? send_provisional_keepalive_with_sdp : send_provisional_keepalive, pvt); + /* schedule the provisional keepalive */ + pvt->provisional_keepalive_data->sched_id = ast_sched_add(sched, + PROVIS_KEEPALIVE_TIMEOUT, + with_sdp ? send_provisional_keepalive_with_sdp : send_provisional_keepalive, + pvt->provisional_keepalive_data); + + /* if schedule was unsuccessful, remove the scheduler's ref */ + if (pvt->provisional_keepalive_data->sched_id == -1) { + ao2_ref(pvt->provisional_keepalive_data, -1); + } } /*! \brief Transmit response on SIP request*/ @@ -2399,7 +2486,7 @@ static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmitty /* If we are sending a final response to an INVITE, stop retransmitting provisional responses */ if (p->initreq.method == SIP_INVITE && reliable == XMIT_CRITICAL) { - AST_SCHED_DEL(sched, p->provisional_keepalive_sched_id); + remove_provisional_keepalive_sched(p); } res = (reliable) ? @@ -3297,7 +3384,13 @@ static int __sip_destroy(struct sip_pvt *p, int lockowner) AST_SCHED_DEL(sched, p->waitid); AST_SCHED_DEL(sched, p->autokillid); AST_SCHED_DEL(sched, p->request_queue_sched_id); - AST_SCHED_DEL(sched, p->provisional_keepalive_sched_id); + + remove_provisional_keepalive_sched(p); + if (p->provisional_keepalive_data) { + ast_mutex_lock(&p->lock); + p->provisional_keepalive_data = unref_provisional_keepalive(p->provisional_keepalive_data); + ast_mutex_unlock(&p->lock); + } if (p->rtp) { ast_rtp_destroy(p->rtp); @@ -3783,7 +3876,7 @@ static int sip_hangup(struct ast_channel *ast) } } else { /* Incoming call, not up */ const char *res; - AST_SCHED_DEL(sched, p->provisional_keepalive_sched_id); + remove_provisional_keepalive_sched(p); if (p->hangupcause && (res = hangup_cause2sip(p->hangupcause))) transmit_response_reliable(p, res, &p->initreq); else @@ -4681,7 +4774,6 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si p->waitid = -1; p->autokillid = -1; p->request_queue_sched_id = -1; - p->provisional_keepalive_sched_id = -1; p->subscribed = NONE; p->stateid = -1; p->prefs = default_prefs; /* Set default codecs for this call */ @@ -18824,6 +18916,8 @@ static int reload_config(enum channelreloadreason reason) ast_log(LOG_WARNING, "Unable to set SIP TOS to %s\n", ast_tos2str(global_tos_sip)); } } + } else if (setsockopt(sipsock, IPPROTO_IP, IP_TOS, &global_tos_sip, sizeof(global_tos_sip))) { + ast_log(LOG_WARNING, "Unable to set SIP TOS to %s\n", ast_tos2str(global_tos_sip)); } ast_mutex_unlock(&netlock); diff --git a/configs/say.conf.sample b/configs/say.conf.sample index 5971d756c..25c369862 100644 --- a/configs/say.conf.sample +++ b/configs/say.conf.sample @@ -101,16 +101,25 @@ _[n]um:X00 => num:${SAY:0:1}, digits/hundred _[n]um:XXX => num:${SAY:0:1}, digits/hundred, num:${SAY:1} + _[n]um:X000 => num:${SAY:0:1}, digits/thousand _[n]um:XXXX => num:${SAY:0:1}, digits/thousand, num:${SAY:1} + _[n]um:XX000 => num:${SAY:0:2}, digits/thousand _[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2} + _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand _[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:3} + _[n]um:X000000 => num:${SAY:0:1}, digits/million _[n]um:XXXXXXX => num:${SAY:0:1}, digits/million, num:${SAY:1} + _[n]um:XX000000 => num:${SAY:0:2}, digits/million _[n]um:XXXXXXXX => num:${SAY:0:2}, digits/million, num:${SAY:2} + _[n]um:XXX000000 => num:${SAY:0:3}, digits/million _[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/million, num:${SAY:3} + _[n]um:X000000000 => num:${SAY:0:1}, digits/billion _[n]um:XXXXXXXXXX => num:${SAY:0:1}, digits/billion, num:${SAY:1} + _[n]um:XX000000000 => num:${SAY:0:2}, digits/billion _[n]um:XXXXXXXXXXX => num:${SAY:0:2}, digits/billion, num:${SAY:2} + _[n]um:XXX000000000 => num:${SAY:0:3}, digits/billion _[n]um:XXXXXXXXXXXX => num:${SAY:0:3}, digits/billion, num:${SAY:3} ; enumeration @@ -118,7 +127,8 @@ _e[n]um:1X => digits/h-${SAY} _e[n]um:[2-9]0 => digits/h-${SAY} _e[n]um:[2-9][1-9] => num:${SAY:0:1}0, digits/h-${SAY:1} - _e[n]um:[1-9]XX => num:${SAY:0:1}, digits/hundred, enum:${SAY:1} + _e[n]um:[1-9]00 => num:${SAY:0:1}, digits/h-hundred + _e[n]um:[1-9]XX => num:${SAY:0:1}, digits/h-hundred, enum:${SAY:1} [en_GB](date-base,digit-base,en-base) _[n]um:XXX => num:${SAY:0:1}, digits/hundred, vm-and, num:${SAY:1} @@ -134,16 +144,31 @@ _[n]um:[2-9]00 => num:${SAY:0:1}, digits/hundred _[n]um:[2-9]XX => num:${SAY:0:1}, digits/hundred, num:${SAY:1} + _[n]um:1000 => digits/thousand _[n]um:1XXX => digits/thousand, num:${SAY:1} + _[n]um:[2-9]000 => num:${SAY:0:1}, digits/thousands _[n]um:[2-9]XXX => num:${SAY:0:1}, digits/thousands, num:${SAY:1} + _[n]um:XX000 => num:${SAY:0:2}, digits/thousands _[n]um:XXXXX => num:${SAY:0:2}, digits/thousands, num:${SAY:2} + _[n]um:XXX000 => num:${SAY:0:3}, digits/thousands _[n]um:XXXXXX => num:${SAY:0:3}, digits/thousands, num:${SAY:3} + _[n]um:1000000 => num:${SAY:0:1}, digits/million _[n]um:1XXXXXX => num:${SAY:0:1}, digits/million, num:${SAY:1} + _[n]um:[2-9]000000 => num:${SAY:0:1}, digits/millions _[n]um:[2-9]XXXXXX => num:${SAY:0:1}, digits/millions, num:${SAY:1} + _[n]um:XX000000 => num:${SAY:0:2}, digits/millions _[n]um:XXXXXXXX => num:${SAY:0:2}, digits/millions, num:${SAY:2} + _[n]um:XXX000000 => num:${SAY:0:3}, digits/millions _[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/millions, num:${SAY:3} + _[n]um:X000000000 => num:${SAY:0:1}, digits/billion + _[n]um:XXXXXXXXXX => num:${SAY:0:1}, digits/billion, num:${SAY:1} + _[n]um:XX000000000 => num:${SAY:0:2}, digits/billion + _[n]um:XXXXXXXXXXX => num:${SAY:0:2}, digits/billion, num:${SAY:2} + _[n]um:XXX000000000 => num:${SAY:0:3}, digits/billion + _[n]um:XXXXXXXXXXXX => num:${SAY:0:3}, digits/billion, num:${SAY:3} + _datetime::. => date:AdBY 'digits/at' IMp:${SAY} _date::. => date:AdBY:${SAY} _time::. => date:IMp:${SAY} @@ -163,14 +188,23 @@ _[n]um:1XX => digits/ein, digits/hundred, num:${SAY:1} _[n]um:[2-9]00 => digits/${SAY:0:1}, digits/hundred _[n]um:[2-9]XX => digits/${SAY:0:1}, digits/hundred, num:${SAY:1} + + _[n]um:1000 => digits/ein, digits/thousand _[n]um:1XXX => digits/ein, digits/thousand, num:${SAY:1} + _[n]um:[2-9]000 => digits/${SAY:0:1}, digits/thousand _[n]um:[2-9]XXX => digits/${SAY:0:1}, digits/thousand, num:${SAY:1} + _[n]um:XX000 => num:${SAY:0:2}, digits/thousand _[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2} - _[n]um:X00XXX => digits/${SAY:0:1}, digits/hundred, digits/thousand, num:${SAY:3} - _[n]um:XXXXXX => digits/${SAY:0:1}, digits/hundred, num:${SAY:1} + _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand + _[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:1} + + _[n]um:1000000 => digits/eine, digits/million _[n]um:1XXXXXX => digits/eine, digits/million, num:${SAY:1} + _[n]um:[2-9]000000 => digits/${SAY:0:1}, digits/millions _[n]um:[2-9]XXXXXX => digits/${SAY:0:1}, digits/millions, num:${SAY:1} + _[n]um:XX000000 => num:${SAY:0:2}, digits/millions _[n]um:XXXXXXXX => num:${SAY:0:2}, digits/millions, num:${SAY:2} + _[n]um:XXX000000 => num:${SAY:0:3}, digits/millions _[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/millions, num:${SAY:3} _datetime::. => date:AdBY 'digits/at' IMp:${SAY} @@ -192,14 +226,22 @@ _[n]um:[2-9]00 => num:${SAY:0:1}, digits/hundred _[n]um:[2-9]XX => num:${SAY:0:1}, digits/hundred, num:${SAY:1} + _[n]um:1000 => digits/thousand _[n]um:1XXX => digits/thousand, num:${SAY:1} + _[n]um:[2-9]000 => num:${SAY:0:1}, digits/thousand _[n]um:[2-9]XXX => num:${SAY:0:1}, digits/thousand, num:${SAY:1} + _[n]um:XX000 => num:${SAY:0:2}, digits/thousand _[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2} + _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand _[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:3} + _[n]um:1000000 => num:${SAY:0:1}, digits/million _[n]um:1XXXXXX => num:${SAY:0:1}, digits/million, num:${SAY:1} + _[n]um:[2-9]000000 => num:${SAY:0:1}, digits/million _[n]um:[2-9]XXXXXX => num:${SAY:0:1}, digits/million, num:${SAY:1} + _[n]um:XX000000 => num:${SAY:0:2}, digits/million _[n]um:XXXXXXXX => num:${SAY:0:2}, digits/million, num:${SAY:2} + _[n]um:XXX000000 => num:${SAY:0:3}, digits/million _[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/million, num:${SAY:3} _datetime::. => date:AdBY 'digits/at' H 'hours' M 'perc':${SAY} @@ -209,3 +251,51 @@ _pho[n]e:XXXX => num:${SAY:0:2}, num:${SAY:2:2} _pho[n]e:0[1-9]XXXXXXXX => num:${SAY:0:1}, num:${SAY:1:1}, num:${SAY:2:2}, num:${SAY:4:2}, num:${SAY:6:2}, num:${SAY:8:2} _pho[n]e:. => digit:${SAY} + +[da](date-base,digit-base) + _[n]um:0. => num:${SAY:1} + _[n]um:X => digits/${SAY} + _[n]um:1X => digits/${SAY} + _[n]um:[2-9]0 => digits/${SAY} + _[n]um:[2-9][1-9] => digits/${SAY:1}-and, digits/${SAY:0:1}0 + _[n]um:100 => digits/1N, digits/hundred + _[n]um:1XX => digits/1N, digits/hundred, num:${SAY:1} + _[n]um:[2-9]00 => digits/${SAY:0:1}, digits/hundred + _[n]um:[2-9]XX => digits/${SAY:0:1}, digits/hundred, num:${SAY:1} + + _[n]um:1000 => digits/1N, digits/thousand + _[n]um:1XXX => digits/1N, digits/thousand, num:${SAY:1} + _[n]um:[2-9]000 => digits/${SAY:0:1}, digits/thousand + _[n]um:[2-9]XXX => digits/${SAY:0:1}, digits/thousand, num:${SAY:1} + _[n]um:XX000 => num:${SAY:0:2}, digits/thousand + _[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2} + _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand + _[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:3} + + _[n]um:X000000 => digits/${SAY:0:1}, digits/million + _[n]um:XXXXXXX => digits/${SAY:0:1}, digits/million, num:${SAY:1} + _[n]um:XX000000 => num:${SAY:0:2}, digits/millions + _[n]um:XXXXXXXX => num:${SAY:0:2}, digits/millions, num:${SAY:2} + _[n]um:XXX000000 => num:${SAY:0:3}, digits/millions + _[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/millions, num:${SAY:3} + + _[n]um:X000000000 => num:${SAY:0:1}, digits/billion + _[n]um:XXXXXXXXXX => num:${SAY:0:1}, digits/billion, num:${SAY:1} + _[n]um:XX000000000 => num:${SAY:0:2}, digits/billion + _[n]um:XXXXXXXXXXX => num:${SAY:0:2}, digits/billion, num:${SAY:2} + _[n]um:XXX000000000 => num:${SAY:0:3}, digits/billion + _[n]um:XXXXXXXXXXXX => num:${SAY:0:3}, digits/billion, num:${SAY:3} + + _datetime::. => date:AdBY 'digits/at' kM:${SAY} + _date::. => date:AdBY:${SAY} + _time::. => date:HM:${SAY} + + ; enumeration + _e[n]um:X => digits/h-${SAY} + _e[n]um:1X => digits/h-${SAY} + _e[n]um:[2-9]0 => digits/h-${SAY} + _e[n]um:[2-9][1-9] => digits/${SAY:1}-and, digits/h-${SAY:0:1}0 + _e[n]um:100 => digits/1N, digits/h-hundred + _e[n]um:1XX => digits/1N, digits/h-hundred, enum:${SAY:1} + _e[n]um:[2-9]00 => num:${SAY:0:1}, digits/h-hundred + _e[n]um:[2-9]XX => num:${SAY:0:1}, digits/h-hundred, enum:${SAY:1} diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index 9a420f768..deb40781e 100644 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -91,6 +91,19 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ;vmexten=voicemail ; dialplan extension to reach mailbox sets the ; Message-Account in the MWI notify message ; defaults to "asterisk" + +; Codec negotiation +; +; When Asterisk is receiving a call, the codec will initially be set to the +; first codec in the allowed codecs defined for the user receiving the call +; that the caller also indicates that it supports. But, after the caller +; starts sending RTP, Asterisk will switch to using whatever codec the caller +; is sending. +; +; When Asterisk is placing a call, the codec used will be the first codec in +; the allowed codecs that the callee indicates that it supports. Asterisk will +; *not* switch to whatever codec the callee is sending. +; ;disallow=all ; First disallow all codecs ;allow=ulaw ; Allow codecs in order of preference ;allow=ilbc ; see doc/rtp-packetization for framing options diff --git a/contrib/scripts/astcli b/contrib/scripts/astcli new file mode 100755 index 000000000..0ea245f14 --- /dev/null +++ b/contrib/scripts/astcli @@ -0,0 +1,167 @@ +#!/usr/bin/perl -w + +use strict; +use IO::Socket; +use Getopt::Long; + +# Created by: David Van Ginneken +# Bird's the Word Technologies +# davevg@btwtech.com +# +# And distributed under the terms of the GPL +# +my ($user, $pw, $host, $port, $interactive, $save) = (undef, undef, 'localhost', 5038, 0, 0); +my $EOL = "\r\n"; # Standard End of Line +my @commands; +process_credentials('/etc/astcli.conf'); +process_credentials("$ENV{HOME}/.astcli") if defined $ENV{HOME}; +GetOptions("username=s" => \$user, "secret=s" => \$pw, "host=s" => \$host, "port=s" => \$port, "readline" => \$interactive, "write" => \$save); + +$|++; # Auto Flush Output +my $action = join(" ", @ARGV); + +&usage if (!defined $user || !defined $pw); +my $tc = new IO::Socket::INET( + PeerAddr => $host, + PeerPort => $port, + Timeout => 30, + Proto => 'tcp' +) or die "Could not connect to Host: $host on port $port\n"; +if (my $error = login()) { + print STDERR $error; + exit 1; +}; + +if ($save) { + if (-d $ENV{HOME}) { + open DEFAULT, ">$ENV{HOME}/.astcli"; + print DEFAULT "username=$user\n" if $user; + print DEFAULT "password=$pw\n" if $pw; + print DEFAULT "hostname=$host\n" if $host; + print DEFAULT "portno=$port\n" if $port; + close DEFAULT; + } +} + +# Send a single command to the manager connection handle (global $tc). +# Assumes things always work well :-) +sub send_command($) { + my $command = shift; + $tc->send('Action: Command' . $EOL); + $tc->send("Command: $command" . $EOL); + $tc->send($EOL); + my $response = ''; + while (<$tc>) { + if ($_ =~ /--END COMMAND--/) { + $_ =~ s/--END COMMAND--\s*//; + $response .= $_; + last; + } + $response .= $_; + } + $response =~ s/Privilege: Command$EOL//; + $response =~ s/Response: Follows$EOL//; + return $response; +} + +sub login { + my ($response, $message); + $tc->send("Action: Login" . $EOL); + $tc->send("Username: $user" . $EOL); + $tc->send("Secret: $pw" . $EOL); + $tc->send("Events: off" . $EOL); + $tc->send($EOL); + while (<$tc>) { + last if $_ eq $EOL; + $_ =~ s/$EOL//g; + ($response) = $_ =~ /^Response: (.*?)$/ if $_ =~ /^Response:/; + ($message) = $_ =~ /^Message: (.*?)$/ if $_ =~ /^Message:/; + } + return 0 if $response eq 'Success'; + return $message; +} + +sub logoff { + my ($response, $message); + $tc->send("Action: Logoff" . $EOL . $EOL); + return 1; +} + +# If the user asked to send commands from standard input: +if ($action eq '-' || !defined $action || $action eq '') { + if ($interactive) { + eval { require Term::ReadLine;}; + $interactive = scalar($@) ? 0 : 1; + print STDERR "Falling back to standard mode, Unable to load Term::Readline for readline mode\n" unless $interactive; + } + if ($interactive) { + my $term = new Term::ReadLine 'Command Line Interface'; + my $prompt = "$host*CLI> "; + my $attribs = $term->Attribs; + $attribs->{completion_function} = \&tab_completion; + while (defined($_ = $term->readline($prompt))) { + (logoff() and exit) if $_ =~ /exit|quit/; # Give them a way to exit the "terminal" + print send_command($_) if $_ !~ m/^\s*$/; + } + } else { + while (<>) { + chomp; + (logoff() and exit) if $_ =~ /exit|quit/; # If someone accidentally ends up here, let them exit + print send_command($_); + } + } + exit 0; +} + +# Otherwise just send the command: +print send_command($action); + +# parses a configuration file into the global $user and $pw. +sub process_credentials { + # Process the credentials found.. + my $file = shift; + # silently fail if we can't read the file: + return unless (-r $file); + open (my $fh, "<$file") or return; + while (<$fh>) { + chomp; + (undef,$user) = split(/[,=]/, $_) if $_ =~ /user(name)?[,=]/i; + (undef,$pw) = split(/[,=]/, $_) if $_ =~ /(secret|passw(or)?d|pwd?)[,=]/i; + (undef,$host) = split(/[,=]/, $_) if $_ =~ /host(name)?[,=]/i; + (undef,$port) = split(/[,=]/, $_) if $_ =~ /port(num|no)?[,=]/i; + } + close ($fh); +} + +sub usage { + print STDERR "astcli [<options>] [<cli-command>|-]\n"; + print STDERR " -u <name> - Connect as username <name>\n"; + print STDERR " -s <pw> - Connect with secret <pw>\n"; + print STDERR " -h <host> - Connect to host <host> [localhost]\n"; + print STDERR " -p <port> - Connect on TCP port <port> [5038]\n"; + print STDERR " -r - Start a readline session for interactivity\n"; + print STDERR " -w - Save connection options in a configuration file\n"; + print STDERR " You may specify the command as '-' to take commands from stdin.\n"; + exit; +} + +sub tab_completion { + my ($word, $buffer, $offset) = @_; + my %items; + my $lastword = ''; + if ($word eq '') { + $buffer =~ m/(\S+)\s?$/; + $lastword = $1; + #print STDERR "\n\nlastword=\"$lastword\"\n"; + } + + my $res = send_command("_command matchesarray \"$buffer\" \"$word\""); + foreach my $item (split /\s+/, $res) { + $items{$item}++ unless ($item eq '_EOF_' or $item eq '' or $item eq $lastword); + } + + #print STDERR "\nword=\"$word\" buffer=\"$buffer\" offset=\"$offset\" res=\"$res\"\n"; + + return sort keys %items; +} + diff --git a/main/channel.c b/main/channel.c index 1d28515c6..bd64c50fa 100644 --- a/main/channel.c +++ b/main/channel.c @@ -4032,6 +4032,7 @@ int ast_do_masquerade(struct ast_channel *original) void *t_pvt; struct ast_callerid tmpcid; struct ast_channel *clone = original->masq; + struct ast_channel *bridged; struct ast_cdr *cdr; int rformat = original->readformat; int wformat = original->writeformat; @@ -4298,6 +4299,15 @@ int ast_do_masquerade(struct ast_channel *original) pthread_kill(original->blocker, SIGURG); if (option_debug) ast_log(LOG_DEBUG, "Done Masquerading %s (%d)\n", original->name, original->_state); + + if ((bridged = ast_bridged_channel(original))) { + ast_channel_lock(bridged); + ast_indicate(bridged, AST_CONTROL_SRCCHANGE); + ast_channel_unlock(bridged); + } + + ast_indicate(original, AST_CONTROL_SRCCHANGE); + return 0; } @@ -4679,8 +4689,8 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha ast_set_flag(c0, AST_FLAG_END_DTMF_ONLY); /* Before we enter in and bridge these two together tell them both the source of audio has changed */ - ast_indicate(c0, AST_CONTROL_SRCUPDATE); - ast_indicate(c1, AST_CONTROL_SRCUPDATE); + ast_indicate(c0, AST_CONTROL_SRCCHANGE); + ast_indicate(c1, AST_CONTROL_SRCCHANGE); for (/* ever */;;) { struct timeval now = { 0, }; diff --git a/main/pbx.c b/main/pbx.c index 1ad2d2e1d..e88bdb879 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -492,7 +492,11 @@ static struct pbx_builtin { }; static struct ast_context *contexts; -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_LIST_HEAD_STATIC(apps, ast_app); @@ -6193,22 +6197,22 @@ int load_pbx(void) */ int ast_lock_contexts() { - return ast_rwlock_wrlock(&conlock); + return ast_mutex_lock(&conlock); } int ast_rdlock_contexts(void) { - return ast_rwlock_rdlock(&conlock); + return ast_mutex_lock(&conlock); } int ast_wrlock_contexts(void) { - return ast_rwlock_wrlock(&conlock); + return ast_mutex_lock(&conlock); } int ast_unlock_contexts() { - return ast_rwlock_unlock(&conlock); + return ast_mutex_unlock(&conlock); } /* diff --git a/pbx/pbx_config.c b/pbx/pbx_config.c index 9c51b130c..0bcdf7811 100644 --- a/pbx/pbx_config.c +++ b/pbx/pbx_config.c @@ -2475,13 +2475,14 @@ static int pbx_load_module(void) static int load_module(void) { - if (pbx_load_module()) - return AST_MODULE_LOAD_DECLINE; - + if (static_config && !write_protect_config) ast_cli_register(&cli_dialplan_save); ast_cli_register_multiple(cli_pbx_config, sizeof(cli_pbx_config) / sizeof(struct ast_cli_entry)); + if (pbx_load_module()) + return AST_MODULE_LOAD_DECLINE; + return 0; } |