diff options
author | rmudgett <rmudgett@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-08-20 16:48:10 +0000 |
---|---|---|
committer | rmudgett <rmudgett@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-08-20 16:48:10 +0000 |
commit | b97106edbf460d54203370576160d47325e49710 (patch) | |
tree | d3954c4e1d3ebe7a3d54ebe017e23c933a15f40b | |
parent | f8d0dcac122feafe9ebd0aba502263f829c77667 (diff) |
Merged revisions 283123 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
................
r283123 | rmudgett | 2010-08-20 11:46:22 -0500 (Fri, 20 Aug 2010) | 9 lines
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.6.2@283124 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | apps/app_dial.c | 3 | ||||
-rw-r--r-- | apps/app_readexten.c | 2 | ||||
-rw-r--r-- | channels/chan_dahdi.c | 15 | ||||
-rw-r--r-- | channels/chan_local.c | 20 | ||||
-rw-r--r-- | channels/chan_sip.c | 111 | ||||
-rw-r--r-- | configs/say.conf.sample | 105 | ||||
-rw-r--r-- | configs/sip.conf.sample | 13 | ||||
-rw-r--r-- | doc/tex/asterisk.tex | 3 | ||||
-rw-r--r-- | doc/tex/sounds.tex | 80 | ||||
-rw-r--r-- | include/asterisk/pbx.h | 10 | ||||
-rw-r--r-- | main/cdr.c | 39 | ||||
-rw-r--r-- | main/channel.c | 14 | ||||
-rw-r--r-- | main/pbx.c | 31 | ||||
-rw-r--r-- | main/sched.c | 2 | ||||
-rw-r--r-- | pbx/pbx_config.c | 6 |
15 files changed, 354 insertions, 100 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c index f5309f5ed..f2735a63e 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -2247,8 +2247,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/apps/app_readexten.c b/apps/app_readexten.c index d5075ede8..e20dfff1d 100644 --- a/apps/app_readexten.c +++ b/apps/app_readexten.c @@ -220,7 +220,7 @@ static int readexten_exec(struct ast_channel *chan, void *data) if (res < 1) { /* timeout expired or hangup */ if (ast_check_hangup(chan)) { status = "HANGUP"; - } else { + } else if (x == 0) { pbx_builtin_setvar_helper(chan, arglist.variable, "t"); status = "TIMEOUT"; } diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index fb45564e3..8026ca574 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -3601,7 +3601,16 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout) l = NULL; n = NULL; if (!p->hidecallerid) { - l = ast->cid.cid_num; + /* If we get to the end of this loop without breaking, there's no + * numeric calleridnum. This is done instead of testing for + * "unknown" or the thousands of other ways that the calleridnum + * could be invalid. */ + for (l = ast->cid.cid_num; l && *l; l++) { + if (strchr("0123456789", *l)) { + l = ast->cid.cid_num; + break; + } + } if (!p->hidecalleridname) { n = ast->cid.cid_name; } @@ -7372,7 +7381,7 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d ast_debug(1,"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->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) + if (!p->progress && !p->alerting && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && !p->outgoing) { if (p->pri->pri) { if (!pri_grab(p, p->pri)) { @@ -13542,7 +13551,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 a26b8f718..46451776f 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -384,6 +384,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 dc8e98713..89cfe8f12 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -3104,6 +3104,32 @@ cleanup: return NULL; } +/* this func is used with ao2_callback to unlink/delete all marked + peers */ +static int peer_is_marked(void *peerobj, void *arg, int flags) +{ + struct sip_peer *peer = peerobj; + return peer->the_mark ? CMP_MATCH : 0; +} + + +/* \brief Unlink all marked peers from ao2 containers */ +static void unlink_marked_peers_from_tables(void) +{ + ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, NULL, + "initiating callback to remove marked peers"); + ao2_t_callback(peers_by_ip, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, NULL, + "initiating callback to remove marked peers"); +} + +/* \brief Unlink single peer from all ao2 containers */ +static void unlink_peer_from_tables(struct sip_peer *peer) +{ + ao2_t_unlink(peers, peer, "ao2_unlink of peer from peers table"); + if (peer->addr.sin_addr.s_addr) { + ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table"); + } +} /*! * helper functions to unreference various types of objects. @@ -8130,10 +8156,10 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action int vportno = -1; /*!< RTP Video port number */ int tportno = -1; /*!< RTP Text port number */ int udptlportno = -1; /*!< UDPTL Image port number */ - struct sockaddr_in sin; /*!< media socket address */ - struct sockaddr_in vsin; /*!< video socket address */ - struct sockaddr_in isin; /*!< image socket address */ - struct sockaddr_in tsin; /*!< text socket address */ + struct sockaddr_in sin = { 0, }; /*!< media socket address */ + struct sockaddr_in vsin = { 0, }; /*!< video socket address */ + struct sockaddr_in isin = { 0, }; /*!< image socket address */ + struct sockaddr_in tsin = { 0, }; /*!< text socket address */ /* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */ int peercapability = 0, peernoncodeccapability = 0; @@ -8648,7 +8674,10 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action ast_set_write_format(p->owner, p->owner->writeformat); } - if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && sin.sin_addr.s_addr && (!sendonly || sendonly == -1)) { + if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) + && (sin.sin_addr.s_addr || vsin.sin_addr.s_addr || + isin.sin_addr.s_addr || tsin.sin_addr.s_addr) + && (!sendonly || sendonly == -1)) { ast_queue_control(p->owner, AST_CONTROL_UNHOLD); /* Activate a re-invite */ ast_queue_frame(p->owner, &ast_null_frame); @@ -8664,7 +8693,9 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action if (sip_cfg.notifyhold) sip_peer_hold(p, FALSE); ast_clear_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); /* Clear both flags */ - } else if (!sin.sin_addr.s_addr || (sendonly && sendonly != -1)) { + } else if (!(sin.sin_addr.s_addr || vsin.sin_addr.s_addr || + isin.sin_addr.s_addr || tsin.sin_addr.s_addr) + || (sendonly && sendonly != -1)) { int already_on_hold = ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); ast_queue_control_data(p->owner, AST_CONTROL_HOLD, S_OR(p->mohsuggest, NULL), @@ -11315,27 +11346,30 @@ static int transmit_state_notify(struct sip_pvt *p, int state, int full, int tim int need = strlen(caller->cid.cid_num) + strlen(p->fromdomain) + sizeof("sip:@"); local_target = alloca(need); snprintf(local_target, need, "sip:%s@%s", caller->cid.cid_num, p->fromdomain); - local_display = ast_strdupa(caller->cid.cid_name); + if (!(ast_strlen_zero(caller->cid.cid_name))) { + local_display = ast_strdupa(caller->cid.cid_name); + } ast_channel_unlock(caller); caller = NULL; } + /* We create a fake call-id which the phone will send back in an INVITE + * Replaces header which we can grab and do some magic with. */ + ast_str_append(&tmp, 0, + "<dialog id=\"%s\" call-id=\"pickup-%s\" direction=\"recipient\">\n" + "<remote>\n" + /* See the limitations of this above. Luckily the phone seems to still be + happy when these values are not correct. */ + "<identity display=\"%s\">%s</identity>\n" + "<target uri=\"%s\"/>\n" + "</remote>\n" + "<local>\n" + "<identity>%s</identity>\n" + "<target uri=\"%s\"/>\n" + "</local>\n", + p->exten, p->callid, local_display, local_target, local_target, mto, mto); + } else { + ast_str_append(&tmp, 0, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten); } - - /* We create a fake call-id which the phone will send back in an INVITE - Replaces header which we can grab and do some magic with. */ - ast_str_append(&tmp, 0, - "<dialog id=\"%s\" call-id=\"pickup-%s\" direction=\"recipient\">\n" - "<remote>\n" - /* See the limitations of this above. Luckily the phone seems to still be - happy when these values are not correct. */ - "<identity display=\"%s\">%s</identity>\n" - "<target uri=\"%s\"/>\n" - "</remote>\n" - "<local>\n" - "<identity>%s</identity>\n" - "<target uri=\"%s\"/>\n" - "</local>\n", - p->exten, p->callid, local_display, local_target, local_target, mto, mto); } else { ast_str_append(&tmp, 0, "<dialog id=\"%s\">\n", p->exten); } @@ -12114,7 +12148,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); @@ -12136,12 +12169,13 @@ static int expire_register(const void *data) if (peer->selfdestruct || ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) { - ao2_t_unlink(peers, peer, "ao2_unlink of peer from peers table"); - if (peer->addr.sin_addr.s_addr) { - ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table"); - } + unlink_peer_from_tables(peer); } + /* 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; @@ -15131,14 +15165,6 @@ static int dialog_needdestroy(void *dialogobj, void *arg, int flags) return 0; } -/* this func is used with ao2_callback to unlink/delete all marked - peers */ -static int peer_is_marked(void *peerobj, void *arg, int flags) -{ - struct sip_peer *peer = peerobj; - return peer->the_mark ? CMP_MATCH : 0; -} - /*! \brief Remove temporary realtime objects from memory (CLI) */ /*! \todo XXXX Propably needs an overhaul after removal of the devices */ static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) @@ -15241,8 +15267,7 @@ static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli } ao2_iterator_destroy(&i); if (pruned) { - ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, NULL, - "initiating callback to remove marked peers"); + unlink_marked_peers_from_tables(); ast_cli(a->fd, "%d peers pruned.\n", pruned); } else ast_cli(a->fd, "No peers found to prune.\n"); @@ -23772,6 +23797,8 @@ static void set_peer_defaults(struct sip_peer *peer) peer->timer_t1 = global_t1; peer->timer_b = global_timer_b; clear_peer_mailboxes(peer); + peer->transports = default_transports; + peer->default_outbound_transport = default_primary_transport; } /*! \brief Create temporary peer (used in autocreatepeer mode) */ @@ -23914,6 +23941,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str /* If we have realm authentication information, remove them (reload) */ clear_realm_authentication(peer->auth); peer->auth = NULL; + /* clear the transport information. We will detect if a default value is required after parsing the config */ peer->default_outbound_transport = 0; peer->transports = 0; @@ -25145,6 +25173,8 @@ static int reload_config(enum channelreloadreason reason) ast_netsock_set_qos(sipsock, global_tos_sip, global_cos_sip, "SIP"); } } + } else { + ast_netsock_set_qos(sipsock, global_tos_sip, global_cos_sip, "SIP"); } if (stunaddr.sin_addr.s_addr != 0) { ast_debug(1, "stun to %s:%d\n", @@ -25803,9 +25833,8 @@ static int sip_do_reload(enum channelreloadreason reason) start_poke = time(0); /* Prune peers who still are supposed to be deleted */ - ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, NULL, - "callback to remove marked peers"); - + unlink_marked_peers_from_tables(); + ast_debug(4, "--------------- Done destroying pruned peers\n"); /* Send qualify (OPTIONS) to all peers */ diff --git a/configs/say.conf.sample b/configs/say.conf.sample index 04d7a149c..7df5c1293 100644 --- a/configs/say.conf.sample +++ b/configs/say.conf.sample @@ -106,16 +106,25 @@ mode=old ; method for playing numbers and dates _[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 @@ -123,7 +132,8 @@ mode=old ; method for playing numbers and dates _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} @@ -139,16 +149,31 @@ mode=old ; method for playing numbers and dates _[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} @@ -168,14 +193,23 @@ mode=old ; method for playing numbers and dates _[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} @@ -191,16 +225,25 @@ mode=old ; method for playing numbers and dates _[n]um:[3-9][1-9] => digits/${SAY:0:1}0, num:${SAY:1} _[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} _datetime::. => date:YBdA k 'ora' M 'perc':${SAY} @@ -222,14 +265,22 @@ mode=old ; method for playing numbers and dates _[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} @@ -239,3 +290,51 @@ mode=old ; method for playing numbers and dates _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 516ec7058..24f03b95b 100644 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -188,6 +188,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/doc/tex/asterisk.tex b/doc/tex/asterisk.tex index f9b432fe0..2adf4fad6 100644 --- a/doc/tex/asterisk.tex +++ b/doc/tex/asterisk.tex @@ -139,6 +139,9 @@ reference purposes. \chapter{Packet Loss Concealment} \input{plc.tex} +\chapter{Sounds Packages} + \input{sounds.tex} + \chapter{Development} \section{Backtrace} \input{backtrace.tex} diff --git a/doc/tex/sounds.tex b/doc/tex/sounds.tex new file mode 100644 index 000000000..59091983b --- /dev/null +++ b/doc/tex/sounds.tex @@ -0,0 +1,80 @@ +\section{Introduction} +Asterisk utilizes a variety of sound prompts that are available in several file +formats and languages. Multiple languages and formats can be installed on the +same system, and Asterisk will utilize prompts from languages installed, and +will automatically pick the least CPU intensive format that is available on the +system (based on codecs in use, in additional to the codec and format modules +installed and available). + +In addition to the prompts available with Asterisk, you can create your own sets +of prompts and utilize them as well. This document will tell you how the prompts +available for Asterisk are created so that the prompts you create can be as close +and consistent in the quality and volume levels as those shipped with Asterisk. + +\section{Getting The Sounds Tools} +The sounds tools are available in the publicly accessible repotools repository. +You can check these tools out with Subversion via the following command: + +\begin{astlisting} +\begin{verbatim} +# svn co http://svn.asterisk.org/svn/repotools +\end{verbatim} +\end{astlisting} + +The sound tools are available in the subdirectory sound_tools/ which contains the +following directories: + +\begin{itemize} +\item audiofilter +\item makeg722 +\item scripts +\end{itemize} + +\section{About The Sounds Tools} +The following sections will describe the sound tools in more detail and explain what +they are used for in the sounds package creation process. + +\subsection{audiofilter} +The audiofilter application is used to "tune" the sound files in such a way that +they sound good when being used while in a compressed format. The values in the +scripts for creating the sound files supplied in repotools is essentially a +high-pass filter that drops out audio below 100Hz (or so). + +(There is an ITU specification that states for 8KHz audio that is being compressed +frequencies below a certain threshold should be removed because they make the +resulting compressed audio sound worse than it should.) + +The audiofilter application is used by the 'converter' script located in the +scripts subdirectory of repotools/sound_tools. The values being passed to the +audiofilter application is as follows: + +\begin{astlisting} +\begin{verbatim} +audiofilter -n 0.86916 -1.73829 0.86916 -d 1.00000 -1.74152 0.77536 +\end{verbatim} +\end{astlisting} + + +The two options -n and -d are 'numerator' and 'denominator'. Per the author, +Jean-Marc Valin, "These values are filter coefficients (-n means numerator, -d is +denominator) expressed in the z-transform domain. There represent an elliptic filter +that I designed with Octave such that 'the result sounds good'." + +\subsection{makeg722} +The makeg722 application is used by the 'converters' script to generate the G.722 +sound files that are shipped with Asterisk. It starts with the RAW sound files and +then converts them to G.722. + +\subsection{scripts} +The scripts folder is where all the magic happens. These are the scripts that the +Asterisk open source team use to build the packaged audio files for the various +formats that are distributed with Asterisk. + +\begin{itemize} +\item chkcore - used to check that the contents of core-sounds-$<$lang$>$.txt are in sync +\item chkextra - same as above, but checks the extra sound files +\item mkcore - script used to generate the core sounds packages +\item mkextra - script used to generate the extra sounds packages +\item mkmoh - script used to generate the music on hold packages +\item converters - script used to convert the master files to various formats +\end{itemize} diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h index e35cb9650..4f2d6facb 100644 --- a/include/asterisk/pbx.h +++ b/include/asterisk/pbx.h @@ -1109,20 +1109,12 @@ struct pbx_find_info { const char *data; /* set on return */ const char *foundcontext; /* set on return */ }; - + struct ast_exten *pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, 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 24a12a5e6..a7a096a35 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -78,18 +78,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); @@ -1409,22 +1417,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/channel.c b/main/channel.c index 23e4529e3..3a4ba57a3 100644 --- a/main/channel.c +++ b/main/channel.c @@ -4613,6 +4613,7 @@ int ast_do_masquerade(struct ast_channel *original) void *t_pvt; struct ast_callerid tmpcid; struct ast_channel *clonechan = original->masq; + struct ast_channel *bridged; struct ast_cdr *cdr; int rformat = original->readformat; int wformat = original->writeformat; @@ -4877,6 +4878,15 @@ int ast_do_masquerade(struct ast_channel *original) if (ast_test_flag(original, AST_FLAG_BLOCKING)) pthread_kill(original->blocker, SIGURG); ast_debug(1, "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; } @@ -5336,8 +5346,8 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha manager_bridge_event(1, 1, c0, c1); /* 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 505abf382..aac9bb5d4 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -1119,7 +1119,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); @@ -6655,7 +6659,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(); @@ -6664,15 +6667,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(); @@ -9344,32 +9338,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/sched.c b/main/sched.c index 8699cfbab..0aebb43f1 100644 --- a/main/sched.c +++ b/main/sched.c @@ -589,13 +589,13 @@ int ast_sched_runq(struct sched_context *con) ast_mutex_lock(&con->lock); + when = ast_tvadd(ast_tvnow(), ast_tv(0, 1000)); for (numevents = 0; (current = ast_heap_peek(con->sched_heap, 1)); numevents++) { /* schedule all events which are going to expire within 1ms. * We only care about millisecond accuracy anyway, so this will * help us get more than one event at one time if they are very * close together. */ - when = ast_tvadd(ast_tvnow(), ast_tv(0, 1000)); if (ast_tvcmp(current->when, when) != -1) { break; } diff --git a/pbx/pbx_config.c b/pbx/pbx_config.c index ae409edfd..aeb69638d 100644 --- a/pbx/pbx_config.c +++ b/pbx/pbx_config.c @@ -1738,13 +1738,13 @@ 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, ARRAY_LEN(cli_pbx_config)); + if (pbx_load_module()) + return AST_MODULE_LOAD_DECLINE; + return AST_MODULE_LOAD_SUCCESS; } |