main/asterisk: upgrade to 11.0.0 from testing/asterisk

- re-enable libasteriskssl as the uclibc bug should be fixed now
This commit is contained in:
Timo Teräs 2012-11-05 08:29:18 +02:00
parent 24734f342b
commit defd141cdf
18 changed files with 102 additions and 2346 deletions

View File

@ -1,71 +0,0 @@
------------------------------------------------------------------------
r345735 | pabelanger | 2011-11-21 18:40:17 +0200 (Mon, 21 Nov 2011) | 7 lines
Add #tryinclude statement
This provides the same functionality as #include however an asterisk module will
still load if the filename does not exist.
Review: https://reviewboard.asterisk.org/r/1476/
diff --git a/CHANGES b/CHANGES
index 4d106f6..bfc7301 100644
--- a/CHANGES
+++ b/CHANGES
@@ -389,6 +389,12 @@ SIP Changes
* Addition of the 'auth_options_requests' option for turning on and off
authentication for OPTIONS requests in chan_sip.
+Configuration files
+-------------------
+ * Add #tryinclude statement for config files. This provides the same
+ functionality as the #include statement however an asterisk module will
+ still load if the filename does not exist. Using the #include statement
+ Asterisk will not allow the module to load.
IAX2 Changes
-----------
diff --git a/main/config.c b/main/config.c
index 498ae99..e76a43f 100644
--- a/main/config.c
+++ b/main/config.c
@@ -1202,6 +1202,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
char *cur2;
char real_inclusion_name[256];
int do_include = 0; /* otherwise, it is exec */
+ int try_include = 0;
cur++;
c = cur;
@@ -1221,6 +1222,9 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
}
if (!strcasecmp(cur, "include")) {
do_include = 1;
+ } else if (!strcasecmp(cur, "tryinclude")) {
+ do_include = 1;
+ try_include = 1;
} else if (!strcasecmp(cur, "exec")) {
if (!ast_opt_exec_includes) {
ast_log(LOG_WARNING, "Cannot perform #exec unless execincludes option is enabled in asterisk.conf (options section)!\n");
@@ -1232,8 +1236,8 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
}
if (c == NULL) {
- ast_log(LOG_WARNING, "Directive '#%s' needs an argument (%s) at line %d of %s\n",
- do_include ? "include" : "exec",
+ ast_log(LOG_WARNING, "Directive '#%s' needs an argument (%s) at line %d of %s\n",
+ do_include ? "include / tryinclude" : "exec",
do_include ? "filename" : "/path/to/executable",
lineno,
configfile);
@@ -1278,7 +1282,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
do_include = ast_config_internal_load(cur, cfg, flags, real_inclusion_name, who_asked) ? 1 : 0;
if (!ast_strlen_zero(exec_file))
unlink(exec_file);
- if (!do_include) {
+ if (!do_include && !try_include) {
ast_log(LOG_ERROR, "The file '%s' was listed as a #include but it does not exist.\n", cur);
return -1;
}
------------------------------------------------------------------------

View File

@ -1,8 +1,8 @@
# Contributor: Timo Teras <timo.teras@iki.fi>
# Maintainer: Timo Teras <timo.teras@iki.fi>
pkgname=asterisk
pkgver=10.9.0
pkgrel=0
pkgver=11.0.0
pkgrel=2
pkgdesc="Asterisk: A Module Open Source PBX System"
pkgusers="asterisk"
pkggroups="asterisk"
@ -22,9 +22,6 @@ subpackages="$pkgname-dev $pkgname-doc $pkgname-pgsql $pkgname-odbc
source="http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-${pkgver/_/-}.tar.gz
100-uclibc-daemon.patch
101-caps-uclibc.patch
900-tryinclude.patch
ASTERISK-13456.patch
ASTERISK-18977.patch
ASTERISK-18995.patch
ASTERISK-19109.patch
ASTERISK-20527.patch
@ -184,14 +181,11 @@ sound_en() {
chown -R asterisk:asterisk "$subpkgdir"/var/*/asterisk
}
md5sums="2fb85dc753584ac13692c27f9749c6cb asterisk-10.9.0.tar.gz
md5sums="e23c8535a425253764bdddeee49d1778 asterisk-11.0.0.tar.gz
b00c9d98ce2ad445501248a197c6e436 100-uclibc-daemon.patch
6e1129e30c4fd2c25c86c81685a485a9 101-caps-uclibc.patch
b794636266cc573f0dda730fba634567 900-tryinclude.patch
8dea1081693fb5bf63b380ad6d56e316 ASTERISK-13456.patch
1ddadef41aa7120e168738b6f3ed8917 ASTERISK-18977.patch
bc6713f5434e07b79d3afdd155461d72 ASTERISK-18995.patch
a22bb1d513d026564cb40ec213b1ae7f ASTERISK-19109.patch
146befabe95798a67c58d8ac00d397a6 ASTERISK-19109.patch
676ca42ee1859d8a7bae4345ede5eb89 ASTERISK-20527.patch
74cd25a5638a94ef51e9f4ede2fd28f2 asterisk.initd
ed31d7ba37bcf8b0346dcf8593c395f0 asterisk.confd

View File

@ -1,363 +0,0 @@
Add callbackextension matching & realtime callbackextensions
This patch is based on the one by David Vossel, developer extrodinaire, at
https://reviewboard.asterisk.org/r/344/. If multiple peers are defined with the
same host/port, but differing callbackextensions, it chooses the peer with the
matching callbackextension. Since callbackextension creates an outbound
registration with the callbackextension as the Contact address, matching an
incoming request by that (in addition to the host/port) makes a lot of sense.
This patch also adds support for callbackextension to realtime by querying all
peers with callbackextensions on reload and adding registrations for them.
(closes issue ASTERISK-13456)
Review: https://reviewboard.asterisk.org/r/344/
Review: https://reviewboard.asterisk.org/r/1717/
diff --git a/CHANGES b/CHANGES
index de18858..6a22ae2 100644
--- a/CHANGES
+++ b/CHANGES
@@ -24,6 +24,12 @@ SIP Changes
The LastMsgsSent value has been re-added with the same functionality as in
previous versions of Asterisk.
+ * Add support to realtime for the 'callbackextension' option
+ * When multiple peers exist with the same address, but differing
+ callbackextension options, incoming requests that are matched by address
+ will be matched to the peer with the matching callbackextension if it is
+ available.
+
------------------------------------------------------------------------------
--- Functionality changes since Asterisk 10.3.0 ------------------------------
------------------------------------------------------------------------------
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 41fb935..ad8da22 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1456,13 +1456,14 @@ static void destroy_association(struct sip_peer *peer);
static void set_insecure_flags(struct ast_flags *flags, const char *value, int lineno);
static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask, struct ast_variable *v);
static void set_socket_transport(struct sip_socket *socket, int transport);
+static int peer_ipcmp_cb_full(void *obj, void *arg, void *data, int flags);
/* Realtime device support */
static void realtime_update_peer(const char *peername, struct ast_sockaddr *addr, const char *username, const char *fullcontact, const char *useragent, int expirey, unsigned short deprecated_username, int lastms);
static void update_peer(struct sip_peer *p, int expire);
static struct ast_variable *get_insecure_variable_from_config(struct ast_config *config);
static const char *get_name_from_variable(const struct ast_variable *var);
-static struct sip_peer *realtime_peer(const char *peername, struct ast_sockaddr *sin, int devstate_only, int which_objects);
+static struct sip_peer *realtime_peer(const char *peername, struct ast_sockaddr *sin, char *callbackexten, int devstate_only, int which_objects);
static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
/*--- Internal UA client handling (outbound registrations) */
@@ -4891,7 +4892,7 @@ static struct ast_variable *realtime_peer_get_sippeer_helper(const char **name,
/* If varregs is NULL, we don't use sipregs. If we return true, then *name is
* set. Using empty if-bodies instead of goto's while avoiding unnecessary
* indents. */
-static int realtime_peer_by_addr(const char **name, struct ast_sockaddr *addr, const char *ipaddr, struct ast_variable **var, struct ast_variable **varregs)
+static int realtime_peer_by_addr(const char **name, struct ast_sockaddr *addr, const char *ipaddr, const char *callbackexten, struct ast_variable **var, struct ast_variable **varregs)
{
char portstring[6]; /* up to 5 digits plus null terminator */
ast_copy_string(portstring, ast_sockaddr_stringify_port(addr), sizeof(portstring));
@@ -4899,8 +4900,11 @@ static int realtime_peer_by_addr(const char **name, struct ast_sockaddr *addr, c
/* We're not finding this peer by this name anymore. Reset it. */
*name = NULL;
- /* First check for fixed IP hosts */
- if ((*var = ast_load_realtime("sippeers", "host", ipaddr, "port", portstring, SENTINEL))) {
+ /* First check for fixed IP hosts with matching callbackextensions, if specified */
+ if (!ast_strlen_zero(callbackexten) && (*var = ast_load_realtime("sippeers", "host", ipaddr, "port", portstring, "callbackextension", callbackexten, SENTINEL))) {
+ ;
+ /* Check for fixed IP hosts */
+ } else if ((*var = ast_load_realtime("sippeers", "host", ipaddr, "port", portstring, SENTINEL))) {
;
/* Check for registered hosts (in sipregs) */
} else if (varregs && (*varregs = ast_load_realtime("sipregs", "ipaddr", ipaddr, "port", portstring, SENTINEL)) &&
@@ -4951,6 +4955,38 @@ static int realtime_peer_by_addr(const char **name, struct ast_sockaddr *addr, c
return 1;
}
+static int register_realtime_peers_with_callbackextens(void)
+{
+ struct ast_config *cfg;
+ char *cat = NULL;
+
+ if (!(ast_check_realtime("sippeers"))) {
+ return 0;
+ }
+
+ /* This is hacky. We want name to be the cat, so it is the first property */
+ if (!(cfg = ast_load_realtime_multientry("sippeers", "name LIKE", "%", "callbackextension LIKE", "%", SENTINEL))) {
+ return -1;
+ }
+
+ while ((cat = ast_category_browse(cfg, cat))) {
+ struct sip_peer *peer;
+ struct ast_variable *var = ast_category_root(cfg, cat);
+
+ if (!(peer = build_peer(cat, var, NULL, TRUE, FALSE))) {
+ continue;
+ }
+ ast_log(LOG_NOTICE, "Created realtime peer '%s' for registration\n", peer->name);
+
+ peer->is_realtime = 1;
+ sip_unref_peer(peer, "register_realtime_peers: Done registering releasing");
+ }
+
+ ast_config_destroy(cfg);
+
+ return 0;
+}
+
/*! \brief realtime_peer: Get peer from realtime storage
* Checks the "sippeers" realtime family from extconfig.conf
* Checks the "sipregs" realtime family from extconfig.conf if it's configured.
@@ -4960,7 +4996,7 @@ static int realtime_peer_by_addr(const char **name, struct ast_sockaddr *addr, c
* \note This is never called with both newpeername and addr at the same time.
* If you do, be prepared to get a peer with a different name than newpeername.
*/
-static struct sip_peer *realtime_peer(const char *newpeername, struct ast_sockaddr *addr, int devstate_only, int which_objects)
+static struct sip_peer *realtime_peer(const char *newpeername, struct ast_sockaddr *addr, char *callbackexten, int devstate_only, int which_objects)
{
struct sip_peer *peer = NULL;
struct ast_variable *var = NULL;
@@ -4976,7 +5012,7 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct ast_sockad
if (newpeername && realtime_peer_by_name(&newpeername, addr, ipaddr, &var, realtimeregs ? &varregs : NULL)) {
;
- } else if (addr && realtime_peer_by_addr(&newpeername, addr, ipaddr, &var, realtimeregs ? &varregs : NULL)) {
+ } else if (addr && realtime_peer_by_addr(&newpeername, addr, ipaddr, callbackexten, &var, realtimeregs ? &varregs : NULL)) {
;
} else {
return NULL;
@@ -5052,20 +5088,7 @@ static int find_by_name(void *obj, void *arg, void *data, int flags)
return CMP_MATCH | CMP_STOP;
}
-/*!
- * \brief Locate device by name or ip address
- * \param peer, sin, realtime, devstate_only, transport
- * \param which_objects Define which objects should be matched when doing a lookup
- * by name. Valid options are FINDUSERS, FINDPEERS, or FINDALLDEVICES.
- * Note that this option is not used at all when doing a lookup by IP.
- *
- * This is used on find matching device on name or ip/port.
- * If the device was declared as type=peer, we don't match on peer name on incoming INVITEs.
- *
- * \note Avoid using this function in new functions if there is a way to avoid it,
- * since it might cause a database lookup.
- */
-struct sip_peer *sip_find_peer(const char *peer, struct ast_sockaddr *addr, int realtime, int which_objects, int devstate_only, int transport)
+static struct sip_peer *sip_find_peer_full(const char *peer, struct ast_sockaddr *addr, char *callbackexten, int realtime, int which_objects, int devstate_only, int transport)
{
struct sip_peer *p = NULL;
struct sip_peer tmp_peer;
@@ -5077,10 +5100,10 @@ struct sip_peer *sip_find_peer(const char *peer, struct ast_sockaddr *addr, int
ast_sockaddr_copy(&tmp_peer.addr, addr);
tmp_peer.flags[0].flags = 0;
tmp_peer.transports = transport;
- p = ao2_t_find(peers_by_ip, &tmp_peer, OBJ_POINTER, "ao2_find in peers_by_ip table"); /* WAS: p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, name, sip_addr_hashfunc, 1, sip_addrcmp); */
+ p = ao2_t_callback_data(peers_by_ip, OBJ_POINTER, peer_ipcmp_cb_full, &tmp_peer, callbackexten, "ao2_find in peers_by_ip table");
if (!p) {
ast_set_flag(&tmp_peer.flags[0], SIP_INSECURE_PORT);
- p = ao2_t_find(peers_by_ip, &tmp_peer, OBJ_POINTER, "ao2_find in peers_by_ip table 2"); /* WAS: p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, name, sip_addr_hashfunc, 1, sip_addrcmp); */
+ p = ao2_t_callback_data(peers_by_ip, OBJ_POINTER, peer_ipcmp_cb_full, &tmp_peer, callbackexten, "ao2_find in peers_by_ip table 2");
if (p) {
return p;
}
@@ -5088,7 +5111,9 @@ struct sip_peer *sip_find_peer(const char *peer, struct ast_sockaddr *addr, int
}
if (!p && (realtime || devstate_only)) {
- p = realtime_peer(peer, addr, devstate_only, which_objects);
+ /* realtime_peer will return a peer with matching callbackexten if possible, otherwise one matching
+ * without the callbackexten */
+ p = realtime_peer(peer, addr, callbackexten, devstate_only, which_objects);
if (p) {
switch (which_objects) {
case FINDUSERS:
@@ -5112,6 +5137,29 @@ struct sip_peer *sip_find_peer(const char *peer, struct ast_sockaddr *addr, int
return p;
}
+/*!
+ * \brief Locate device by name or ip address
+ * \param peer, sin, realtime, devstate_only, transport
+ * \param which_objects Define which objects should be matched when doing a lookup
+ * by name. Valid options are FINDUSERS, FINDPEERS, or FINDALLDEVICES.
+ * Note that this option is not used at all when doing a lookup by IP.
+ *
+ * This is used on find matching device on name or ip/port.
+ * If the device was declared as type=peer, we don't match on peer name on incoming INVITEs.
+ *
+ * \note Avoid using this function in new functions if there is a way to avoid it,
+ * since it might cause a database lookup.
+ */
+struct sip_peer *sip_find_peer(const char *peer, struct ast_sockaddr *addr, int realtime, int which_objects, int devstate_only, int transport)
+{
+ return sip_find_peer_full(peer, addr, NULL, realtime, which_objects, devstate_only, transport);
+}
+
+static struct sip_peer *sip_find_peer_by_ip_and_exten(struct ast_sockaddr *addr, char *callbackexten, int transport)
+{
+ return sip_find_peer_full(NULL, addr, callbackexten, TRUE, FINDPEERS, FALSE, transport);
+}
+
/*! \brief Set nat mode on the various data sockets */
static void do_setnat(struct sip_pvt *p)
{
@@ -8418,16 +8466,16 @@ static struct sip_pvt *find_call(struct sip_request *req, struct ast_sockaddr *a
/*! \brief create sip_registry object from register=> line in sip.conf and link into reg container */
static int sip_register(const char *value, int lineno)
{
- struct sip_registry *reg;
+ struct sip_registry *reg, *tmp;
if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) {
ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n");
return -1;
}
- ast_atomic_fetchadd_int(&regobjs, 1);
ASTOBJ_INIT(reg);
+ ast_copy_string(reg->name, value, sizeof(reg->name));
if (sip_parse_register_line(reg, default_expiry, value, lineno)) {
registry_unref(reg, "failure to parse, unref the reg pointer");
return -1;
@@ -8438,8 +8486,13 @@ static int sip_register(const char *value, int lineno)
reg->refresh = reg->expiry = reg->configured_expiry = default_expiry;
}
- /* Add the new registry entry to the list */
- ASTOBJ_CONTAINER_LINK(&regl, reg);
+ /* Add the new registry entry to the list, but only if it isn't already there */
+ if ((tmp = ASTOBJ_CONTAINER_FIND(&regl, reg->name))) {
+ registry_unref(tmp, "throw away found registry");
+ } else {
+ ast_atomic_fetchadd_int(&regobjs, 1);
+ ASTOBJ_CONTAINER_LINK(&regl, reg);
+ }
/* release the reference given by ASTOBJ_INIT. The container has another reference */
registry_unref(reg, "unref the reg pointer");
@@ -16433,7 +16486,14 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
/* Then find devices based on IP */
if (!peer) {
- peer = sip_find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE, p->socket.type);
+ char *uri_tmp, *callback = NULL, *dummy;
+ uri_tmp = ast_strdupa(uri2);
+ parse_uri(uri_tmp, "sip:,sips:", &callback, &dummy, &dummy, &dummy);
+ if (!ast_strlen_zero(callback) && (peer = sip_find_peer_by_ip_and_exten(&p->recv, callback, p->socket.type))) {
+ ; /* found, fall through */
+ } else {
+ peer = sip_find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE, p->socket.type);
+ }
}
}
@@ -28283,7 +28343,6 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
time_t regseconds = 0;
struct ast_flags peerflags[3] = {{(0)}};
struct ast_flags mask[3] = {{(0)}};
- char callback[256] = "";
struct sip_peer tmp_peer;
const char *srvlookup = NULL;
static int deprecation_warning = 1;
@@ -28588,7 +28647,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
} else if (!strcasecmp(v->name, "regexten")) {
ast_string_field_set(peer, regexten, v->value);
} else if (!strcasecmp(v->name, "callbackextension")) {
- ast_copy_string(callback, v->value, sizeof(callback));
+ ast_string_field_set(peer, callback, v->value);
} else if (!strcasecmp(v->name, "amaflags")) {
format = ast_cdr_amaflags2int(v->value);
if (format < 0) {
@@ -28960,9 +29019,9 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
ast_free_ha(oldha);
ast_free_ha(olddirectmediaha);
- if (!ast_strlen_zero(callback)) { /* build string from peer info */
+ if (!ast_strlen_zero(peer->callback)) { /* build string from peer info */
char *reg_string;
- if (ast_asprintf(&reg_string, "%s?%s:%s@%s/%s", peer->name, peer->username, !ast_strlen_zero(peer->remotesecret) ? peer->remotesecret : peer->secret, peer->tohost, callback) >= 0) {
+ if (ast_asprintf(&reg_string, "%s?%s:%s@%s/%s", peer->name, peer->username, !ast_strlen_zero(peer->remotesecret) ? peer->remotesecret : peer->secret, peer->tohost, peer->callback) >= 0) {
sip_register(reg_string, 0); /* XXX TODO: count in registry_count */
ast_free(reg_string);
}
@@ -30116,6 +30175,8 @@ static int reload_config(enum channelreloadreason reason)
/* Release configuration from memory */
ast_config_destroy(cfg);
+ register_realtime_peers_with_callbackextens();
+
/* Load the list of manual NOTIFY types to support */
if (notify_types) {
ast_config_destroy(notify_types);
@@ -31013,9 +31074,17 @@ static int peer_iphash_cb(const void *obj, const int flags)
*
* \note the peer's addr struct provides to fields combined to make a key: the sin_addr.s_addr and sin_port fields.
*/
-static int peer_ipcmp_cb(void *obj, void *arg, int flags)
+static int peer_ipcmp_cb_full(void *obj, void *arg, void *data, int flags)
{
struct sip_peer *peer = obj, *peer2 = arg;
+ char *callback = data;
+
+ if (!ast_strlen_zero(callback) && strcasecmp(peer->callback, callback)) {
+ /* We require a callback extension match, but don't have one */
+ return 0;
+ }
+
+ /* At this point, we match the callback extension if we need to. Carry on. */
if (ast_sockaddr_cmp_addr(&peer->addr, &peer2->addr)) {
/* IP doesn't match */
@@ -31038,6 +31107,10 @@ static int peer_ipcmp_cb(void *obj, void *arg, int flags)
(CMP_MATCH | CMP_STOP) : 0;
}
+static int peer_ipcmp_cb(void *obj, void *arg, int flags)
+{
+ return peer_ipcmp_cb_full(obj, arg, NULL, flags);
+}
static int threadt_hash_cb(const void *obj, const int flags)
{
diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h
index ab2ed1b..48626aa 100644
--- a/channels/sip/include/sip.h
+++ b/channels/sip/include/sip.h
@@ -1246,6 +1246,7 @@ struct sip_peer {
AST_STRING_FIELD(mwi_from); /*!< Name to place in From header for outgoing NOTIFY requests */
AST_STRING_FIELD(engine); /*!< RTP Engine to use */
AST_STRING_FIELD(unsolicited_mailbox); /*!< Mailbox to store received unsolicited MWI NOTIFY messages information in */
+ AST_STRING_FIELD(callback); /*!< Callback extension */
);
struct sip_socket socket; /*!< Socket used for this peer */
enum sip_transport default_outbound_transport; /*!< Peer Registration may change the default outbound transport.
@@ -1331,7 +1332,7 @@ struct sip_peer {
* \todo Convert this to astobj2
*/
struct sip_registry {
- ASTOBJ_COMPONENTS_FULL(struct sip_registry,1,1);
+ ASTOBJ_COMPONENTS_FULL(struct sip_registry, 80, 1);
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(callid); /*!< Global Call-ID */
AST_STRING_FIELD(realm); /*!< Authorization realm */
diff --git a/contrib/realtime/postgresql/realtime.sql b/contrib/realtime/postgresql/realtime.sql
index f14cd79..7b8dcec 100644
--- a/contrib/realtime/postgresql/realtime.sql
+++ b/contrib/realtime/postgresql/realtime.sql
@@ -72,7 +72,8 @@ lastms integer DEFAULT 0 NOT NULL,
defaultuser character varying(80),
fullcontact character varying(80),
regserver character varying(30),
-useragent character varying(40)
+useragent character varying(40),
+callbackextension character varying(40)
);
drop table voicemail_users;

View File

@ -1,63 +0,0 @@
--- a/res/res_musiconhold.c.orig
+++ b/res/res_musiconhold.c
@@ -158,6 +158,7 @@
char name[MAX_MUSICCLASS];
struct ast_format origwfmt;
struct ast_format mohwfmt;
+ int announcement;
int samples;
int sample_queue;
int pos;
@@ -173,6 +174,7 @@
#define MOH_SORTALPHA (1 << 4)
#define MOH_CACHERTCLASSES (1 << 5) /*!< Should we use a separate instance of MOH for each user or not */
+#define MOH_ANNOUNCEMENT (1 << 6)
/* Custom astobj2 flag */
#define MOH_NOTDELETED (1 << 30) /*!< Find only records that aren't deleted? */
@@ -183,6 +185,7 @@
char name[MAX_MUSICCLASS];
char dir[256];
char args[256];
+ char announcement[80];
char mode[80];
char digit;
/*! A dynamically sized array to hold the list of filenames in "files" mode */
@@ -278,6 +281,7 @@
}
state->save_pos = state->pos;
+ state->announcement = 0;
state->class = mohclass_unref(state->class, "Unreffing channel's music class upon deactivation of generator");
}
@@ -293,6 +297,16 @@
chan->stream = NULL;
}
+ if (ast_test_flag(state->class, MOH_ANNOUNCEMENT) && state->announcement == 0) {
+ state->announcement = 1;
+ if (ast_openstream_full(chan, state->class->announcement, chan->language, 1)) {
+ ast_debug(1, "%s Opened announcement '%s'\n", chan->name, state->class->announcement);
+ return 0;
+ }
+ } else {
+ state->announcement = 0;
+ }
+
if (!state->class->total_files) {
ast_log(LOG_WARNING, "No files available for class '%s'\n", state->class->name);
return -1;
@@ -1731,7 +1745,10 @@
ast_copy_string(class->dir, var->value, sizeof(class->dir));
else if (!strcasecmp(var->name, "application"))
ast_copy_string(class->args, var->value, sizeof(class->args));
- else if (!strcasecmp(var->name, "digit") && (isdigit(*var->value) || strchr("*#", *var->value)))
+ else if (!strcasecmp(var->name, "announcement")) {
+ ast_copy_string(class->announcement, var->value, sizeof(class->announcement));
+ ast_set_flag(class, MOH_ANNOUNCEMENT);
+ } else if (!strcasecmp(var->name, "digit") && (isdigit(*var->value) || strchr("*#", *var->value)))
class->digit = *var->value;
else if (!strcasecmp(var->name, "random"))
ast_set2_flag(class, ast_true(var->value), MOH_RANDOMIZE);

View File

@ -1,11 +1,39 @@
commit 0fad0f8a679cbb0609056528ac157476dd4e5877
Author: Timo Teräs <timo.teras@iki.fi>
Date: Wed Dec 28 08:30:54 2011 +0200
From 806946c35cf0560248e63fea53c4d82426a2034a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
Date: Wed, 5 Sep 2012 10:07:05 +0300
Subject: [PATCH] ASTERISK-19109: Implement deaf participant support for
ConfBridge
Support 'deaf' participants in ConfBridge
---
CHANGES | 3 +
apps/app_confbridge.c | 218 ++++++++++++++++++++++++++++++---
apps/confbridge/conf_config_parser.c | 14 +++
apps/confbridge/include/confbridge.h | 6 +
bridges/bridge_multiplexed.c | 2 +-
bridges/bridge_simple.c | 2 +-
bridges/bridge_softmix.c | 38 +++---
configs/confbridge.conf.sample | 5 +
include/asterisk/bridging_features.h | 2 +
include/asterisk/bridging_technology.h | 15 +++
main/bridging.c | 22 ++++
11 files changed, 294 insertions(+), 33 deletions(-)
diff --git a/CHANGES b/CHANGES
index c3c9891..2efa17b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -66,6 +66,9 @@ ConfBridge
file will be played to the user, and only the user, upon joining the
conference bridge.
+ * Added support for deaf participants with CLI commands, manager actions
+ and ConfBridge DTMF actions to toggle the deaf state.
+
Dial
-------------------
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index d5609b7..8569f5c 100644
index 90954b8..0455be4 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -185,6 +185,30 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
@ -64,7 +92,7 @@ index d5609b7..8569f5c 100644
case CONF_SOUND_ONLY_ONE:
return S_OR(custom_sounds->onlyone, "conf-onlyone");
case CONF_SOUND_THERE_ARE:
@@ -1423,10 +1458,13 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
@@ -1504,10 +1539,13 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
@ -79,7 +107,7 @@ index d5609b7..8569f5c 100644
if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_DROP_SILENCE)) {
conference_bridge_user.tech_args.drop_silence = 1;
@@ -1587,6 +1625,20 @@ static int action_toggle_mute_participants(struct conference_bridge *conference_
@@ -1668,6 +1706,20 @@ static int action_toggle_mute_participants(struct conference_bridge *conference_
return 0;
}
@ -100,7 +128,7 @@ index d5609b7..8569f5c 100644
static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
{
char *file_copy = ast_strdupa(playback_file);
@@ -1775,6 +1827,11 @@ static int execute_menu_entry(struct conference_bridge *conference_bridge,
@@ -1856,6 +1908,11 @@ static int execute_menu_entry(struct conference_bridge *conference_bridge,
case MENU_ACTION_PARTICIPANT_COUNT:
announce_user_count(conference_bridge, conference_bridge_user);
break;
@ -112,7 +140,7 @@ index d5609b7..8569f5c 100644
case MENU_ACTION_PLAYBACK:
if (!stop_prompts) {
res |= action_playback(bridge_channel, menu_action->data.playback_file);
@@ -2038,13 +2095,13 @@ static int generic_lock_unlock_helper(int lock, const char *conference)
@@ -2119,13 +2176,13 @@ static int generic_lock_unlock_helper(int lock, const char *conference)
}
/* \internal
@ -128,12 +156,12 @@ index d5609b7..8569f5c 100644
{
struct conference_bridge *bridge = NULL;
struct conference_bridge tmp;
@@ -2062,10 +2119,44 @@ static int generic_mute_unmute_helper(int mute, const char *conference, const ch
@@ -2143,10 +2200,44 @@ static int generic_mute_unmute_helper(int mute, const char *conference, const ch
}
}
if (participant) {
- participant->features.mute = mute;
- ast_test_suite_event_notify("CONF_MUTE", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", participant->chan->name, participant->features.mute ? "muted" : "unmuted", bridge->b_profile.name, participant->chan->name);
- ast_test_suite_event_notify("CONF_MUTE", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", ast_channel_name(participant->chan), participant->features.mute ? "muted" : "unmuted", bridge->b_profile.name, ast_channel_name(participant->chan));
+ const char *state, *verb;
+
+ switch (action) {
@ -165,10 +193,10 @@ index d5609b7..8569f5c 100644
+ "Message: participant %s %s\r\n"
+ "Conference: %s\r\n"
+ "Channel: %s",
+ participant->chan->name,
+ ast_channel_name(participant->chan),
+ verb,
+ bridge->b_profile.name,
+ participant->chan->name);
+ ast_channel_name(participant->chan));
+ }
} else {
- res = -2;;
@ -176,7 +204,7 @@ index d5609b7..8569f5c 100644
}
ao2_unlock(bridge);
ao2_ref(bridge, -1);
@@ -2073,9 +2164,10 @@ static int generic_mute_unmute_helper(int mute, const char *conference, const ch
@@ -2154,9 +2245,10 @@ static int generic_mute_unmute_helper(int mute, const char *conference, const ch
return res;
}
@ -189,7 +217,7 @@ index d5609b7..8569f5c 100644
if (res == -1) {
ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
@@ -2084,7 +2176,24 @@ static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)
@@ -2165,7 +2257,24 @@ static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)
ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]);
return -1;
}
@ -215,7 +243,7 @@ index d5609b7..8569f5c 100644
return 0;
}
@@ -2106,7 +2215,7 @@ static char *handle_cli_confbridge_mute(struct ast_cli_entry *e, int cmd, struct
@@ -2187,7 +2296,7 @@ static char *handle_cli_confbridge_mute(struct ast_cli_entry *e, int cmd, struct
return CLI_SHOWUSAGE;
}
@ -224,7 +252,7 @@ index d5609b7..8569f5c 100644
return CLI_SUCCESS;
}
@@ -2129,7 +2238,53 @@ static char *handle_cli_confbridge_unmute(struct ast_cli_entry *e, int cmd, stru
@@ -2210,7 +2319,53 @@ static char *handle_cli_confbridge_unmute(struct ast_cli_entry *e, int cmd, stru
return CLI_SHOWUSAGE;
}
@ -279,7 +307,7 @@ index d5609b7..8569f5c 100644
return CLI_SUCCESS;
}
@@ -2277,6 +2432,8 @@ static struct ast_cli_entry cli_confbridge[] = {
@@ -2358,6 +2513,8 @@ static struct ast_cli_entry cli_confbridge[] = {
AST_CLI_DEFINE(handle_cli_confbridge_kick, "Kick participants out of conference bridges."),
AST_CLI_DEFINE(handle_cli_confbridge_mute, "Mute a participant."),
AST_CLI_DEFINE(handle_cli_confbridge_unmute, "Unmute a participant."),
@ -288,7 +316,7 @@ index d5609b7..8569f5c 100644
AST_CLI_DEFINE(handle_cli_confbridge_lock, "Lock a conference."),
AST_CLI_DEFINE(handle_cli_confbridge_unlock, "Unlock a conference."),
AST_CLI_DEFINE(handle_cli_confbridge_start_record, "Start recording a conference"),
@@ -2411,10 +2568,11 @@ static int action_confbridgelistrooms(struct mansession *s, const struct message
@@ -2492,10 +2649,11 @@ static int action_confbridgelistrooms(struct mansession *s, const struct message
return 0;
}
@ -301,7 +329,7 @@ index d5609b7..8569f5c 100644
int res = 0;
if (ast_strlen_zero(conference)) {
@@ -2430,7 +2588,7 @@ static int action_mute_unmute_helper(struct mansession *s, const struct message
@@ -2511,7 +2669,7 @@ static int action_mute_unmute_helper(struct mansession *s, const struct message
return 0;
}
@ -310,7 +338,7 @@ index d5609b7..8569f5c 100644
if (res == -1) {
astman_send_error(s, m, "No Conference by that name found.");
@@ -2440,17 +2598,41 @@ static int action_mute_unmute_helper(struct mansession *s, const struct message
@@ -2521,17 +2679,41 @@ static int action_mute_unmute_helper(struct mansession *s, const struct message
return 0;
}
@ -355,7 +383,7 @@ index d5609b7..8569f5c 100644
}
static int action_lock_unlock_helper(struct mansession *s, const struct message *m, int lock)
@@ -2737,6 +2919,8 @@ static int unload_module(void)
@@ -2818,6 +3000,8 @@ static int unload_module(void)
res |= ast_manager_unregister("ConfbridgeListRooms");
res |= ast_manager_unregister("ConfbridgeMute");
res |= ast_manager_unregister("ConfbridgeUnmute");
@ -364,7 +392,7 @@ index d5609b7..8569f5c 100644
res |= ast_manager_unregister("ConfbridgeKick");
res |= ast_manager_unregister("ConfbridgeUnlock");
res |= ast_manager_unregister("ConfbridgeLock");
@@ -2778,6 +2962,8 @@ static int load_module(void)
@@ -2860,6 +3044,8 @@ static int load_module(void)
res |= ast_manager_register_xml("ConfbridgeListRooms", EVENT_FLAG_REPORTING, action_confbridgelistrooms);
res |= ast_manager_register_xml("ConfbridgeMute", EVENT_FLAG_CALL, action_confbridgemute);
res |= ast_manager_register_xml("ConfbridgeUnmute", EVENT_FLAG_CALL, action_confbridgeunmute);
@ -374,19 +402,10 @@ index d5609b7..8569f5c 100644
res |= ast_manager_register_xml("ConfbridgeUnlock", EVENT_FLAG_CALL, action_confbridgeunlock);
res |= ast_manager_register_xml("ConfbridgeLock", EVENT_FLAG_CALL, action_confbridgelock);
diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c
index 9bb8b2a..3cf7a32 100644
index f4a9604..8a02de7 100644
--- a/apps/confbridge/conf_config_parser.c
+++ b/apps/confbridge/conf_config_parser.c
@@ -153,6 +153,8 @@ static int set_user_option(const char *name, const char *value, struct user_prof
ast_set2_flag(u_profile, ast_true(value), USER_OPT_MARKEDUSER);
} else if (!strcasecmp(name, "startmuted")) {
ast_set2_flag(u_profile, ast_true(value), USER_OPT_STARTMUTED);
+ } else if (!strcasecmp(name, "startdeaf")) {
+ ast_set2_flag(u_profile, ast_true(value), USER_OPT_STARTDEAF);
} else if (!strcasecmp(name, "music_on_hold_when_empty")) {
ast_set2_flag(u_profile, ast_true(value), USER_OPT_MUSICONHOLD);
} else if (!strcasecmp(name, "quiet")) {
@@ -231,6 +233,10 @@ static int set_sound(const char *sound_name, const char *sound_file, struct brid
@@ -279,6 +279,10 @@ static int set_sound(const char *sound_name, const char *sound_file, struct brid
ast_string_field_set(sounds, muted, sound_file);
} else if (!strcasecmp(sound_name, "sound_unmuted")) {
ast_string_field_set(sounds, unmuted, sound_file);
@ -397,7 +416,7 @@ index 9bb8b2a..3cf7a32 100644
} else if (!strcasecmp(sound_name, "sound_there_are")) {
ast_string_field_set(sounds, thereare, sound_file);
} else if (!strcasecmp(sound_name, "sound_other_in_party")) {
@@ -541,6 +547,7 @@ static int add_action_to_menu_entry(struct conf_menu_entry *menu_entry, enum con
@@ -418,6 +422,7 @@ static int add_action_to_menu_entry(struct conf_menu_entry *menu_entry, enum con
switch (id) {
case MENU_ACTION_NOOP:
case MENU_ACTION_TOGGLE_MUTE:
@ -405,7 +424,17 @@ index 9bb8b2a..3cf7a32 100644
case MENU_ACTION_INCREASE_LISTENING:
case MENU_ACTION_DECREASE_LISTENING:
case MENU_ACTION_INCREASE_TALKING:
@@ -1029,6 +1036,8 @@ static char *handle_cli_confbridge_show_bridge_profile(struct ast_cli_entry *e,
@@ -708,6 +713,9 @@ static char *handle_cli_confbridge_show_user_profile(struct ast_cli_entry *e, in
ast_cli(a->fd,"Start Muted: %s\n",
u_profile.flags & USER_OPT_STARTMUTED?
"true" : "false");
+ ast_cli(a->fd,"Start Deaf: %s\n",
+ u_profile.flags & USER_OPT_STARTDEAF?
+ "true" : "false");
ast_cli(a->fd,"MOH When Empty: %s\n",
u_profile.flags & USER_OPT_MUSICONHOLD ?
"enabled" : "disabled");
@@ -896,6 +904,8 @@ static char *handle_cli_confbridge_show_bridge_profile(struct ast_cli_entry *e,
ast_cli(a->fd,"sound_kicked: %s\n", conf_get_sound(CONF_SOUND_KICKED, b_profile.sounds));
ast_cli(a->fd,"sound_muted: %s\n", conf_get_sound(CONF_SOUND_MUTED, b_profile.sounds));
ast_cli(a->fd,"sound_unmuted: %s\n", conf_get_sound(CONF_SOUND_UNMUTED, b_profile.sounds));
@ -414,7 +443,7 @@ index 9bb8b2a..3cf7a32 100644
ast_cli(a->fd,"sound_there_are: %s\n", conf_get_sound(CONF_SOUND_THERE_ARE, b_profile.sounds));
ast_cli(a->fd,"sound_other_in_party: %s\n", conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, b_profile.sounds));
ast_cli(a->fd,"sound_place_into_conference: %s\n", conf_get_sound(CONF_SOUND_PLACE_IN_CONF, b_profile.sounds));
@@ -1140,6 +1149,9 @@ static char *handle_cli_confbridge_show_menu(struct ast_cli_entry *e, int cmd, s
@@ -1021,6 +1031,9 @@ static char *handle_cli_confbridge_show_menu(struct ast_cli_entry *e, int cmd, s
case MENU_ACTION_TOGGLE_MUTE:
ast_cli(a->fd, "toggle_mute");
break;
@ -424,8 +453,16 @@ index 9bb8b2a..3cf7a32 100644
case MENU_ACTION_NOOP:
ast_cli(a->fd, "no_op");
break;
@@ -1268,6 +1281,7 @@ int conf_load_config(int reload)
aco_option_register(&cfg_info, "admin", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_ADMIN);
aco_option_register(&cfg_info, "marked", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_MARKEDUSER);
aco_option_register(&cfg_info, "startmuted", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_STARTMUTED);
+ aco_option_register(&cfg_info, "startdeaf", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_STARTDEAF);
aco_option_register(&cfg_info, "music_on_hold_when_empty", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_MUSICONHOLD);
aco_option_register(&cfg_info, "quiet", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_QUIET);
aco_option_register_custom(&cfg_info, "announce_user_count_all", ACO_EXACT, user_types, "no", announce_user_count_all_handler, 0);
diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h
index 5337e22..c601fa8 100644
index d3ead35..3d773c5 100644
--- a/apps/confbridge/include/confbridge.h
+++ b/apps/confbridge/include/confbridge.h
@@ -57,6 +57,7 @@ enum user_profile_flags {
@ -444,7 +481,7 @@ index 5337e22..c601fa8 100644
MENU_ACTION_PLAYBACK,
MENU_ACTION_PLAYBACK_AND_CONTINUE,
MENU_ACTION_INCREASE_LISTENING,
@@ -143,6 +145,8 @@ enum conf_sounds {
@@ -142,6 +144,8 @@ enum conf_sounds {
CONF_SOUND_KICKED,
CONF_SOUND_MUTED,
CONF_SOUND_UNMUTED,
@ -453,7 +490,7 @@ index 5337e22..c601fa8 100644
CONF_SOUND_ONLY_ONE,
CONF_SOUND_THERE_ARE,
CONF_SOUND_OTHER_IN_PARTY,
@@ -169,6 +173,8 @@ struct bridge_profile_sounds {
@@ -168,6 +172,8 @@ struct bridge_profile_sounds {
AST_STRING_FIELD(kicked);
AST_STRING_FIELD(muted);
AST_STRING_FIELD(unmuted);
@ -463,7 +500,7 @@ index 5337e22..c601fa8 100644
AST_STRING_FIELD(thereare);
AST_STRING_FIELD(otherinparty);
diff --git a/bridges/bridge_multiplexed.c b/bridges/bridge_multiplexed.c
index e004dfd..7add614 100644
index cd30266..190f790 100644
--- a/bridges/bridge_multiplexed.c
+++ b/bridges/bridge_multiplexed.c
@@ -386,7 +386,7 @@ static enum ast_bridge_write_result multiplexed_bridge_write(struct ast_bridge *
@ -476,7 +513,7 @@ index e004dfd..7add614 100644
return AST_BRIDGE_WRITE_SUCCESS;
diff --git a/bridges/bridge_simple.c b/bridges/bridge_simple.c
index 14864df..d4270ff 100644
index 69e4114..1623ce0 100644
--- a/bridges/bridge_simple.c
+++ b/bridges/bridge_simple.c
@@ -81,7 +81,7 @@ static enum ast_bridge_write_result simple_bridge_write(struct ast_bridge *bridg
@ -489,7 +526,7 @@ index 14864df..d4270ff 100644
return AST_BRIDGE_WRITE_SUCCESS;
diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c
index 7632f36..7946c79 100644
index 52e5551..5754e41 100644
--- a/bridges/bridge_softmix.c
+++ b/bridges/bridge_softmix.c
@@ -435,7 +435,7 @@ static void softmix_pass_dtmf(struct ast_bridge *bridge, struct ast_bridge_chann
@ -546,7 +583,7 @@ index 7632f36..7946c79 100644
sc->have_frame = 0;
}
@@ -850,16 +850,23 @@ static int softmix_bridge_thread(struct ast_bridge *bridge)
@@ -850,16 +850,24 @@ static int softmix_bridge_thread(struct ast_bridge *bridge)
ast_mutex_lock(&sc->lock);
@ -568,19 +605,20 @@ index 7632f36..7946c79 100644
+ memcpy(sc->final_buf, buf, softmix_datalen);
+
+ /* process the softmix channel's new write audio */
+ softmix_process_write_audio(&trans_helper, &bridge_channel->chan->rawwriteformat, sc);
+ softmix_process_write_audio(&trans_helper,
+ ast_channel_rawwriteformat(bridge_channel->chan), sc);
}
- sc->write_frame.datalen = softmix_datalen;
- sc->write_frame.samples = softmix_samples;
- memcpy(sc->final_buf, buf, softmix_datalen);
-
- /* process the softmix channel's new write audio */
- softmix_process_write_audio(&trans_helper, &bridge_channel->chan->rawwriteformat, sc);
- softmix_process_write_audio(&trans_helper, ast_channel_rawwriteformat(bridge_channel->chan), sc);
/* The frame is now ready for use... */
sc->have_frame = 1;
diff --git a/configs/confbridge.conf.sample b/configs/confbridge.conf.sample
index d113825..737f92c 100644
index 7484b28..3b0ce85 100644
--- a/configs/confbridge.conf.sample
+++ b/configs/confbridge.conf.sample
@@ -16,6 +16,7 @@ type=user
@ -591,7 +629,7 @@ index d113825..737f92c 100644
;music_on_hold_when_empty=yes ; Sets whether MOH should be played when only
; one person is in the conference or when the
; the user is waiting on a marked user to enter
@@ -209,6 +210,8 @@ type=bridge
@@ -210,6 +211,8 @@ type=bridge
;sound_kicked ; The sound played to a user who has been kicked from the conference.
;sound_muted ; The sound played when the mute option it toggled on.
;sound_unmuted ; The sound played when the mute option it toggled off.
@ -600,7 +638,7 @@ index d113825..737f92c 100644
;sound_only_person ; The sound played when the user is the only person in the conference.
;sound_only_one ; The sound played to a user when there is only one other
; person is in the conference.
@@ -263,6 +266,8 @@ type=bridge
@@ -264,6 +267,8 @@ type=bridge
; toggle_mute ; Toggle turning on and off mute. Mute will make the user silent
; to everyone else, but the user will still be able to listen in.
; continue to collect the dtmf sequence.
@ -649,10 +687,10 @@ index 3d2e870..1ecb4c1 100644
*
* \note All DSP functionality on the bridge has been pushed down to the lowest possible
diff --git a/main/bridging.c b/main/bridging.c
index 9bc0edc..3295dc2 100644
index 465d033..4f67e90 100644
--- a/main/bridging.c
+++ b/main/bridging.c
@@ -336,6 +336,28 @@ void ast_bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel
@@ -337,6 +337,28 @@ void ast_bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel
return;
}
@ -681,3 +719,6 @@ index 9bc0edc..3295dc2 100644
/*! \brief Generic thread loop, TODO: Rethink this/improve it */
static int generic_thread_loop(struct ast_bridge *bridge)
{
--
1.7.12

View File

@ -1 +0,0 @@
asterisk.pre-install

View File

@ -0,0 +1,6 @@
#!/bin/sh
adduser -S -h /var/lib/asterisk -s /bin/false -D asterisk 2>/dev/null
addgroup -S dialout 2>/dev/null
addgroup asterisk dialout 2>/dev/null
exit 0

View File

@ -1,44 +0,0 @@
diff -Nru asterisk-1.6.1-beta4.org/main/asterisk.c asterisk-1.6.1-beta4/main/asterisk.c
--- asterisk-1.6.1-beta4.org/main/asterisk.c 2008-12-12 23:05:58.000000000 +0100
+++ asterisk-1.6.1-beta4/main/asterisk.c 2008-12-23 15:28:21.000000000 +0100
@@ -3295,9 +3295,40 @@
#if HAVE_WORKING_FORK
if (ast_opt_always_fork || !ast_opt_no_fork) {
#ifndef HAVE_SBIN_LAUNCHD
+#ifndef __UCLIBC__
if (daemon(1, 0) < 0) {
ast_log(LOG_ERROR, "daemon() failed: %s\n", strerror(errno));
}
+#else
+ /*
+ * workaround for uClibc-0.9.29 mipsel bug:
+ * recursive mutexes do not work if uClibc daemon() function has been called,
+ * if parent thread locks a mutex
+ * the child thread cannot acquire a lock with the same name
+ * (same code works if daemon() is not called)
+ * but duplication of uClibc daemon.c code in here does work.
+ */
+ int fd;
+ switch (fork()) {
+ case -1:
+ exit(1);
+ case 0:
+ break;
+ default:
+ _exit(0);
+ }
+ if (setsid() == -1)
+ exit(1);
+ if (fork())
+ _exit(0);
+ if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (fd > 2)
+ close(fd);
+ }
+#endif
ast_mainpid = getpid();
/* Blindly re-write pid file since we are forking */
unlink(ast_config_AST_PID);

View File

@ -1,17 +0,0 @@
--- asterisk-1.6.0.18/configure.ac.orig Mon Oct 26 23:13:28 2009
+++ asterisk-1.6.0.18/configure.ac Fri Nov 27 21:42:36 2009
@@ -627,9 +627,11 @@
AST_EXT_LIB_CHECK([CURSES], [curses], [initscr], [curses.h])
-if test "x${OSARCH}" = "xlinux-gnu" ; then
- AST_EXT_LIB_CHECK([CAP], [cap], [cap_from_text], [sys/capability.h])
-fi
+case "${OSARCH}" in
+ linux*)
+ AST_EXT_LIB_CHECK([CAP], [cap], [cap_from_text], [sys/capability.h])
+ ;;
+esac
AST_C_DEFINE_CHECK([DAHDI], [DAHDI_CODE], [dahdi/user.h])

View File

@ -1,54 +0,0 @@
--- a/codecs/gsm/Makefile.org 2008-03-29 11:33:09.000000000 +0100
+++ b/codecs/gsm/Makefile 2008-03-29 11:44:40.000000000 +0100
@@ -37,23 +37,6 @@
######### ppro's, etc, as well as the AMD K6 and K7. The compile will
######### probably require gcc.
-ifeq (, $(findstring $(OSARCH) , Darwin SunOS ))
-ifeq (, $(findstring $(PROC) , x86_64 amd64 ultrasparc sparc64 arm armv5b armeb ppc powerpc ppc64 ia64 s390 bfin mipsel mips))
-ifeq (, $(findstring $(shell uname -m) , ppc ppc64 alpha armv4l s390 ))
-OPTIMIZE+=-march=$(PROC)
-endif
-endif
-endif
-
-#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only.
-#This works for even old (2.96) versions of gcc and provides a small boost either way.
-#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesn't support it.
-#So we go lowest common available by gcc and go a step down, still a step up from
-#the default as we now have a better instruction set to work with. - Belgarath
-ifeq ($(PROC),ultrasparc)
-OPTIMIZE+=-mcpu=v8 -mtune=$(PROC) -O3
-endif
-
PG =
#PG = -g -pg
######### Profiling flags. If you don't know what that means, leave it blank.
@@ -208,12 +191,10 @@
# XXX Keep a space after each findstring argument
# XXX should merge with GSM_OBJECTS
ifeq ($(OSARCH),linux-gnu)
-ifeq (,$(findstring $(shell uname -m) , x86_64 amd64 ppc ppc64 alpha armv4l sparc64 parisc s390 ))
-ifeq (,$(findstring $(PROC) , arm armv5b armeb powerpc ia64 s390 bfin mipsel mips ))
+ifneq ($(K6OPT),)
GSM_SOURCES+= $(SRC)/k6opt.s
endif
endif
-endif
TOAST_SOURCES = $(SRC)/toast.c \
$(SRC)/toast_lin.c \
@@ -260,12 +241,10 @@
$(SRC)/table.o
ifeq ($(OSARCH),linux-gnu)
-ifeq (,$(findstring $(shell uname -m) , x86_64 amd64 ppc ppc64 alpha armv4l sparc64 parisc ))
-ifeq (,$(findstring $(PROC) , arm armv5b armeb powerpc ia64 bfin mipsel mips ))
+ifneq ($(K6OPT),)
GSM_OBJECTS+= $(SRC)/k6opt.o
endif
endif
-endif
TOAST_OBJECTS = $(SRC)/toast.o \
$(SRC)/toast_lin.o \

View File

@ -1,193 +0,0 @@
# Contributor: Timo Teras <timo.teras@iki.fi>
# Maintainer: Timo Teras <timo.teras@iki.fi>
pkgname=asterisk
pkgver=11.0.0
pkgrel=1
pkgdesc="Asterisk: A Module Open Source PBX System"
pkgusers="asterisk"
pkggroups="asterisk"
url="http://www.asterisk.org/"
arch="all"
license="GPL"
depends=
makedepends="autoconf automake libtool ncurses-dev popt-dev newt-dev zlib-dev
postgresql-dev unixodbc-dev dahdi-tools-dev libpri-dev tar
freetds-dev openssl-dev lua-dev alsa-lib-dev spandsp-dev tiff-dev
libresample sqlite-dev wget speex-dev libogg-dev bluez-dev"
install="$pkgname.pre-install $pkgname.pre-upgrade"
subpackages="$pkgname-dev $pkgname-doc $pkgname-pgsql $pkgname-odbc
$pkgname-tds $pkgname-fax $pkgname-sample-config:sample
$pkgname-sounds-moh:sound_moh $pkgname-sounds-en:sound_en
$pkgname-mobile"
source="http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-${pkgver/_/-}.tar.gz
100-uclibc-daemon.patch
101-caps-uclibc.patch
ASTERISK-18995.patch
ASTERISK-19109.patch
ASTERISK-20527.patch
asterisk.initd
asterisk.confd
asterisk.logrotate"
_builddir="$srcdir/$pkgname-${pkgver/_/-}"
prepare() {
cd "$_builddir"
for i in $source; do
case $i in
*.patch) msg "$i"; patch -p1 -i "$srcdir"/$i || return 1;;
esac
done
sed -i -e 's:lua5.1/::' pbx/pbx_lua.c
sed -i -e 's/PBX_ICONV=1/PBX_ICONV=0/g' configure.ac
sed -i -e 's/int foo = res_ninit(NULL);/res_ninit_is_not_really_here();/g' configure.ac
./bootstrap.sh
}
build() {
cd "$_builddir"
SHA1SUM="$PWD"/build_tools/sha1sum-sh ./configure --prefix=/usr \
--sysconfdir=/etc \
--mandir=/usr/share/man \
--infodir=/usr/share/info \
--libdir=/usr/lib \
--localstatedir=/var \
--disable-xmldoc --with-gsm=internal \
--without-iconv --with-popt --with-z --with-newt \
--with-unixodbc --with-postgres --with-tds \
--with-dahdi --with-pri --with-tonezone \
--with-resample \
--with-sqlite3 \
--with-speex \
--with-asound \
--without-x11 \
--with-spandsp \
--with-bluetooth \
--disable-asteriskssl \
|| return 1
# and figure out which modules to build
rm menuselect.makeopts
make menuselect.makeopts
# enable chan_mobile
sed -i -e '/^MENUSELECT_ADDONS=/s/chan_mobile//' menuselect.makeopts
make ASTCFLAGS="$CFLAGS" ASTLDFLAGS="$LDFLAGS" || return 1
}
package() {
cd "$_builddir"
make -j1 DESTDIR="$pkgdir" install
install -d "$pkgdir"/var/run/asterisk
install -d "$pkgdir"/var/lib/asterisk
install -m755 -D "$srcdir"/$pkgname.initd "$pkgdir"/etc/init.d/$pkgname
install -m644 -D "$srcdir"/$pkgname.confd "$pkgdir"/etc/conf.d/$pkgname
install -m644 -D "$srcdir"/$pkgname.logrotate \
"$pkgdir"/etc/logrotate.d/$pkgname
chown -R asterisk:asterisk "$pkgdir"/var/*/asterisk
chown -R asterisk:asterisk "$pkgdir"/etc/asterisk
chmod -R u=rwX,g=rX,o= "$pkgdir"/etc/asterisk
}
_move_dir() {
for DIR in "$@"; do
local dest=`dirname "$subpkgdir/$DIR"`
echo mkdir -p $dest
mkdir -p "$dest"
echo mv "$pkgdir"/$DIR $dest
mv "$pkgdir"/"$DIR" "$dest"
done
}
_find_and_move() {
local pattern="$1"
cd "$pkgdir" || return 1
find -name "$pattern" -type f | while read f; do
local dest="$subpkgdir/${f%/*}"
mkdir -p "$dest"
mv "$f" "$dest"
done
}
doc() {
default_doc
}
dev() {
default_dev
depends="asterisk"
}
pgsql() {
depends=
install=
_find_and_move '*_pgsql*'
}
odbc() {
depends=
install=
_find_and_move '*odbc*'
}
tds() {
depends=
install=
_find_and_move '*_tds*'
}
fax() {
depends=
install=
_find_and_move '*_fax*'
}
mobile() {
depends=
install=
_find_and_move '*_mobile*'
}
sample() {
arch="noarch"
pkgdesc="Sample configuration files for asterisk"
cd "$_builddir"
mkdir -p "$subpkgdir"/var/lib/asterisk/phoneprov
make -j1 samples DESTDIR="$subpkgdir"
chown -R asterisk:asterisk "$subpkgdir"/var/*/asterisk
chown -R asterisk:asterisk "$subpkgdir"/etc/asterisk
chmod -R u=rwX,g=rX,o= "$subpkgdir"/etc/asterisk
}
sound_moh() {
arch="noarch"
pkgdesc="Default on-hold music files for asterisk"
depends=
install=
_move_dir var/lib/asterisk/moh
chown -R asterisk:asterisk "$subpkgdir"/var/*/asterisk
}
sound_en() {
arch="noarch"
pkgdesc="English sound files for asterisk"
depends=
install=
_move_dir var/lib/asterisk/sounds/en
chown -R asterisk:asterisk "$subpkgdir"/var/*/asterisk
}
md5sums="e23c8535a425253764bdddeee49d1778 asterisk-11.0.0.tar.gz
b00c9d98ce2ad445501248a197c6e436 100-uclibc-daemon.patch
6e1129e30c4fd2c25c86c81685a485a9 101-caps-uclibc.patch
bc6713f5434e07b79d3afdd155461d72 ASTERISK-18995.patch
146befabe95798a67c58d8ac00d397a6 ASTERISK-19109.patch
676ca42ee1859d8a7bae4345ede5eb89 ASTERISK-20527.patch
74cd25a5638a94ef51e9f4ede2fd28f2 asterisk.initd
ed31d7ba37bcf8b0346dcf8593c395f0 asterisk.confd
3e65172275684373e1a25c8a11224411 asterisk.logrotate"

View File

@ -1,358 +0,0 @@
--- /dev/null 2011-11-29 09:02:40.279581283 +0200
+++ b/formats/format_ogg_speex.c 2011-12-08 15:57:12.000000000 +0200
@@ -0,0 +1,355 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2011, Timo Teräs
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief OGG/Speex streams.
+ * \arg File name extension: spx
+ * \ingroup formats
+ */
+
+/*** MODULEINFO
+ <depend>speex</depend>
+ <depend>ogg</depend>
+ <support_level>extended</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/mod_format.h"
+#include "asterisk/module.h"
+
+#include <speex/speex_header.h>
+#include <ogg/ogg.h>
+
+#define BLOCK_SIZE 4096 /* buffer size for feeding OGG routines */
+#define BUF_SIZE 200
+
+struct speex_desc { /* format specific parameters */
+ /* structures for handling the Ogg container */
+ ogg_sync_state oy;
+ ogg_stream_state os;
+ ogg_page og;
+ ogg_packet op;
+
+ int format_id;
+ int serialno;
+
+ /*! \brief Indicates whether an End of Stream condition has been detected. */
+ int eos;
+};
+
+static int read_packet(struct ast_filestream *fs)
+{
+ struct speex_desc *s = (struct speex_desc *)fs->_private;
+ char *buffer;
+ int result;
+ size_t bytes;
+
+ while (1) {
+ /* Get one packet */
+ result = ogg_stream_packetout(&s->os, &s->op);
+ if (result > 0) {
+ if (s->op.bytes>=5 && !memcmp(s->op.packet, "Speex", 5))
+ s->serialno = s->os.serialno;
+ if (s->serialno == -1 || s->os.serialno != s->serialno)
+ continue;
+ return 0;
+ }
+
+ if (result < 0)
+ ast_log(LOG_WARNING,
+ "Corrupt or missing data at this page position; continuing...\n");
+
+ /* No more packets left in the current page... */
+ if (s->eos) {
+ /* No more pages left in the stream */
+ return -1;
+ }
+
+ while (!s->eos) {
+ /* See if OGG has any pages in it's internal buffers */
+ result = ogg_sync_pageout(&s->oy, &s->og);
+ if (result > 0) {
+ /* Read all streams. */
+ if (ogg_page_serialno(&s->og) != s->os.serialno)
+ ogg_stream_reset_serialno(&s->os, ogg_page_serialno(&s->og));
+ /* Yes, OGG has more pages in it's internal buffers,
+ add the page to the stream state */
+ result = ogg_stream_pagein(&s->os, &s->og);
+ if (result == 0) {
+ /* Yes, got a new,valid page */
+ if (ogg_page_eos(&s->og) &&
+ ogg_page_serialno(&s->og) == s->serialno)
+ s->eos = 1;
+ break;
+ }
+ ast_log(LOG_WARNING,
+ "Invalid page in the bitstream; continuing...\n");
+ }
+
+ if (result < 0)
+ ast_log(LOG_WARNING,
+ "Corrupt or missing data in bitstream; continuing...\n");
+
+ /* No, we need to read more data from the file descrptor */
+ /* get a buffer from OGG to read the data into */
+ buffer = ogg_sync_buffer(&s->oy, BLOCK_SIZE);
+ bytes = fread(buffer, 1, BLOCK_SIZE, fs->f);
+ ogg_sync_wrote(&s->oy, bytes);
+ if (bytes == 0)
+ s->eos = 1;
+ }
+ }
+}
+
+/*!
+ * \brief Create a new OGG/Speex filestream and set it up for reading.
+ * \param fs File that points to on disk storage of the OGG/Speex data.
+ * \param expected_rate The expected Speex format (sampling rate).
+ * \return The new filestream.
+ */
+static int ogg_speex_open(struct ast_filestream *fs, int format_id, int expected_rate)
+{
+ char *buffer;
+ size_t bytes;
+ struct speex_desc *s = (struct speex_desc *)fs->_private;
+ SpeexHeader *hdr = NULL;
+ int i, result;
+
+ s->format_id = format_id;
+ s->serialno = -1;
+ ogg_sync_init(&s->oy);
+
+ buffer = ogg_sync_buffer(&s->oy, BLOCK_SIZE);
+ bytes = fread(buffer, 1, BLOCK_SIZE, fs->f);
+ ogg_sync_wrote(&s->oy, bytes);
+
+ result = ogg_sync_pageout(&s->oy, &s->og);
+ if (result != 1) {
+ if(bytes < BLOCK_SIZE) {
+ ast_log(LOG_ERROR, "Run out of data...\n");
+ } else {
+ ast_log(LOG_ERROR, "Input does not appear to be an Ogg bitstream.\n");
+ }
+ ogg_sync_clear(&s->oy);
+ return -1;
+ }
+
+ ogg_stream_init(&s->os, ogg_page_serialno(&s->og));
+ if (ogg_stream_pagein(&s->os, &s->og) < 0) {
+ ast_log(LOG_ERROR, "Error reading first page of Ogg bitstream data.\n");
+ goto error;
+ }
+
+ if (read_packet(fs) < 0) {
+ ast_log(LOG_ERROR, "Error reading initial header packet.\n");
+ goto error;
+ }
+
+ hdr = speex_packet_to_header((char*)s->op.packet, s->op.bytes);
+ if (memcmp(hdr->speex_string, "Speex ", 8)) {
+ ast_log(LOG_ERROR, "OGG container does not contain Speex audio!\n");
+ goto error;
+ }
+ if (hdr->frames_per_packet != 1) {
+ ast_log(LOG_ERROR, "Only one frame-per-packet OGG/Speex files are currently supported!\n");
+ goto error;
+ }
+ if (hdr->nb_channels != 1) {
+ ast_log(LOG_ERROR, "Only monophonic OGG/Speex files are currently supported!\n");
+ goto error;
+ }
+ if (hdr->rate != expected_rate) {
+ ast_log(LOG_ERROR, "Unexpected sampling rate (%d != %d)!\n",
+ hdr->rate, expected_rate);
+ goto error;
+ }
+
+ /* this packet is the comment */
+ if (read_packet(fs) < 0) {
+ ast_log(LOG_ERROR, "Error reading comment packet.\n");
+ goto error;
+ }
+ for (i = 0; i < hdr->extra_headers; i++) {
+ if (read_packet(fs) < 0) {
+ ast_log(LOG_ERROR, "Error reading extra header packet %d.\n", i+1);
+ goto error;
+ }
+ }
+ free(hdr);
+
+ return 0;
+error:
+ if (hdr)
+ free(hdr);
+ ogg_stream_clear(&s->os);
+ ogg_sync_clear(&s->oy);
+ return -1;
+}
+
+/*!
+ * \brief Close a OGG/Speex filestream.
+ * \param fs A OGG/Speex filestream.
+ */
+static void ogg_speex_close(struct ast_filestream *fs)
+{
+ struct speex_desc *s = (struct speex_desc *)fs->_private;
+
+ ogg_stream_clear(&s->os);
+ ogg_sync_clear(&s->oy);
+}
+
+/*!
+ * \brief Read a frame full of audio data from the filestream.
+ * \param fs The filestream.
+ * \param whennext Number of sample times to schedule the next call.
+ * \return A pointer to a frame containing audio data or NULL ifthere is no more audio data.
+ */
+static struct ast_frame *ogg_speex_read(struct ast_filestream *fs,
+ int *whennext)
+{
+ struct speex_desc *s = (struct speex_desc *)fs->_private;
+
+ if (read_packet(fs) < 0)
+ return NULL;
+
+ fs->fr.frametype = AST_FRAME_VOICE;
+ ast_format_set(&fs->fr.subclass.format, s->format_id, 0);
+ fs->fr.mallocd = 0;
+ AST_FRAME_SET_BUFFER(&fs->fr, fs->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
+ memcpy(fs->fr.data.ptr, s->op.packet, s->op.bytes);
+ fs->fr.datalen = s->op.bytes;
+ fs->fr.samples = *whennext = ast_codec_get_samples(&fs->fr);
+
+ return &fs->fr;
+}
+
+/*!
+ * \brief Trucate an OGG/Speex filestream.
+ * \param s The filestream to truncate.
+ * \return 0 on success, -1 on failure.
+ */
+
+static int ogg_speex_trunc(struct ast_filestream *s)
+{
+ ast_log(LOG_WARNING, "Truncation is not supported on OGG/Speex streams!\n");
+ return -1;
+}
+
+/*!
+ * \brief Seek to a specific position in an OGG/Speex filestream.
+ * \param s The filestream to truncate.
+ * \param sample_offset New position for the filestream, measured in 8KHz samples.
+ * \param whence Location to measure
+ * \return 0 on success, -1 on failure.
+ */
+static int ogg_speex_seek(struct ast_filestream *s, off_t sample_offset, int whence)
+{
+ ast_log(LOG_WARNING, "Seeking is not supported on OGG/Speex streams!\n");
+ return -1;
+}
+
+static off_t ogg_speex_tell(struct ast_filestream *s)
+{
+ ast_log(LOG_WARNING, "Telling is not supported on OGG/Speex streams!\n");
+ return -1;
+}
+
+static int ogg_speex_open_nb(struct ast_filestream *fs)
+{
+ return ogg_speex_open(fs, AST_FORMAT_SPEEX, 8000);
+}
+
+static struct ast_format_def speex_f = {
+ .name = "ogg_speex",
+ .exts = "spx",
+ .open = ogg_speex_open_nb,
+ .seek = ogg_speex_seek,
+ .trunc = ogg_speex_trunc,
+ .tell = ogg_speex_tell,
+ .read = ogg_speex_read,
+ .close = ogg_speex_close,
+ .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
+ .desc_size = sizeof(struct speex_desc),
+};
+
+static int ogg_speex_open_wb(struct ast_filestream *fs)
+{
+ return ogg_speex_open(fs, AST_FORMAT_SPEEX16, 16000);
+}
+
+static struct ast_format_def speex16_f = {
+ .name = "ogg_speex16",
+ .exts = "spx16",
+ .open = ogg_speex_open_wb,
+ .seek = ogg_speex_seek,
+ .trunc = ogg_speex_trunc,
+ .tell = ogg_speex_tell,
+ .read = ogg_speex_read,
+ .close = ogg_speex_close,
+ .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
+ .desc_size = sizeof(struct speex_desc),
+};
+
+static int ogg_speex_open_uwb(struct ast_filestream *fs)
+{
+ return ogg_speex_open(fs, AST_FORMAT_SPEEX32, 32000);
+}
+
+static struct ast_format_def speex32_f = {
+ .name = "ogg_speex32",
+ .exts = "spx32",
+ .open = ogg_speex_open_uwb,
+ .seek = ogg_speex_seek,
+ .trunc = ogg_speex_trunc,
+ .tell = ogg_speex_tell,
+ .read = ogg_speex_read,
+ .close = ogg_speex_close,
+ .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
+ .desc_size = sizeof(struct speex_desc),
+};
+
+static int load_module(void)
+{
+ ast_format_set(&speex_f.format, AST_FORMAT_SPEEX, 0);
+ ast_format_set(&speex16_f.format, AST_FORMAT_SPEEX16, 0);
+ ast_format_set(&speex32_f.format, AST_FORMAT_SPEEX32, 0);
+
+ if (ast_format_def_register(&speex_f) ||
+ ast_format_def_register(&speex16_f) ||
+ ast_format_def_register(&speex32_f))
+ return AST_MODULE_LOAD_FAILURE;
+
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+static int unload_module(void)
+{
+ int res = 0;
+ res |= ast_format_def_unregister(speex_f.name);
+ res |= ast_format_def_unregister(speex16_f.name);
+ res |= ast_format_def_unregister(speex32_f.name);
+ return res;
+}
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "OGG/Speex audio",
+ .load = load_module,
+ .unload = unload_module,
+ .load_pri = AST_MODPRI_APP_DEPEND
+);

View File

@ -1,724 +0,0 @@
From 806946c35cf0560248e63fea53c4d82426a2034a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
Date: Wed, 5 Sep 2012 10:07:05 +0300
Subject: [PATCH] ASTERISK-19109: Implement deaf participant support for
ConfBridge
---
CHANGES | 3 +
apps/app_confbridge.c | 218 ++++++++++++++++++++++++++++++---
apps/confbridge/conf_config_parser.c | 14 +++
apps/confbridge/include/confbridge.h | 6 +
bridges/bridge_multiplexed.c | 2 +-
bridges/bridge_simple.c | 2 +-
bridges/bridge_softmix.c | 38 +++---
configs/confbridge.conf.sample | 5 +
include/asterisk/bridging_features.h | 2 +
include/asterisk/bridging_technology.h | 15 +++
main/bridging.c | 22 ++++
11 files changed, 294 insertions(+), 33 deletions(-)
diff --git a/CHANGES b/CHANGES
index c3c9891..2efa17b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -66,6 +66,9 @@ ConfBridge
file will be played to the user, and only the user, upon joining the
conference bridge.
+ * Added support for deaf participants with CLI commands, manager actions
+ and ConfBridge DTMF actions to toggle the deaf state.
+
Dial
-------------------
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index 90954b8..0455be4 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -185,6 +185,30 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<description>
</description>
</manager>
+ <manager name="ConfbridgeDeafen" language="en_US">
+ <synopsis>
+ Deafen a Confbridge user.
+ </synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+ <parameter name="Conference" required="true" />
+ <parameter name="Channel" required="true" />
+ </syntax>
+ <description>
+ </description>
+ </manager>
+ <manager name="ConfbridgeUndeafen" language="en_US">
+ <synopsis>
+ Undeafen a Confbridge user.
+ </synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+ <parameter name="Conference" required="true" />
+ <parameter name="Channel" required="true" />
+ </syntax>
+ <description>
+ </description>
+ </manager>
<manager name="ConfbridgeKick" language="en_US">
<synopsis>
Kick a Confbridge user.
@@ -273,6 +297,13 @@ static const char app[] = "ConfBridge";
/* Number of buckets our conference bridges container can have */
#define CONFERENCE_BRIDGE_BUCKETS 53
+enum confbridge_feature_action {
+ CONFBRIDGE_FEATURE_MUTE,
+ CONFBRIDGE_FEATURE_UNMUTE,
+ CONFBRIDGE_FEATURE_DEAFEN,
+ CONFBRIDGE_FEATURE_UNDEAFEN
+};
+
/*! \brief Container to hold all conference bridges in progress */
static struct ao2_container *conference_bridges;
@@ -311,6 +342,10 @@ const char *conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds
return S_OR(custom_sounds->muted, "conf-muted");
case CONF_SOUND_UNMUTED:
return S_OR(custom_sounds->unmuted, "conf-unmuted");
+ case CONF_SOUND_DEAFENED:
+ return S_OR(custom_sounds->deafened, "conf-deafened");
+ case CONF_SOUND_UNDEAFENED:
+ return S_OR(custom_sounds->undeafened, "conf-undeafened");
case CONF_SOUND_ONLY_ONE:
return S_OR(custom_sounds->onlyone, "conf-onlyone");
case CONF_SOUND_THERE_ARE:
@@ -1504,10 +1539,13 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
- /* If the caller should be joined already muted, make it so */
+ /* If the caller should be joined already muted or deaf, make it so */
if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_STARTMUTED)) {
conference_bridge_user.features.mute = 1;
}
+ if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_STARTDEAF)) {
+ conference_bridge_user.features.deaf = 1;
+ }
if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_DROP_SILENCE)) {
conference_bridge_user.tech_args.drop_silence = 1;
@@ -1668,6 +1706,20 @@ static int action_toggle_mute_participants(struct conference_bridge *conference_
return 0;
}
+static int action_toggle_deaf(struct conference_bridge *conference_bridge,
+ struct conference_bridge_user *conference_bridge_user,
+ struct ast_channel *chan)
+{
+ /* Deafen or undeafen yourself */
+ conference_bridge_user->features.deaf = (!conference_bridge_user->features.deaf ? 1 : 0);
+ ast_test_suite_event_notify("CONF_DEAF", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", chan->name, conference_bridge_user->features.deaf ? "deafened" : "undeafened", conference_bridge_user->b_profile.name, chan->name);
+
+ return ast_stream_and_wait(chan, (conference_bridge_user->features.deaf ?
+ conf_get_sound(CONF_SOUND_DEAFENED, conference_bridge_user->b_profile.sounds) :
+ conf_get_sound(CONF_SOUND_UNDEAFENED, conference_bridge_user->b_profile.sounds)),
+ "");
+}
+
static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
{
char *file_copy = ast_strdupa(playback_file);
@@ -1856,6 +1908,11 @@ static int execute_menu_entry(struct conference_bridge *conference_bridge,
case MENU_ACTION_PARTICIPANT_COUNT:
announce_user_count(conference_bridge, conference_bridge_user);
break;
+ case MENU_ACTION_TOGGLE_DEAF:
+ res |= action_toggle_deaf(conference_bridge,
+ conference_bridge_user,
+ bridge_channel->chan);
+ break;
case MENU_ACTION_PLAYBACK:
if (!stop_prompts) {
res |= action_playback(bridge_channel, menu_action->data.playback_file);
@@ -2119,13 +2176,13 @@ static int generic_lock_unlock_helper(int lock, const char *conference)
}
/* \internal
- * \brief finds a conference user by channel name and mutes/unmutes them.
+ * \brief finds a conference user by channel name and changes feature bits on it.
*
* \retval 0 success
* \retval -1 conference not found
* \retval -2 user not found
*/
-static int generic_mute_unmute_helper(int mute, const char *conference, const char *user)
+static int generic_feature_action_helper(enum confbridge_feature_action action, const char *conference, const char *user)
{
struct conference_bridge *bridge = NULL;
struct conference_bridge tmp;
@@ -2143,10 +2200,44 @@ static int generic_mute_unmute_helper(int mute, const char *conference, const ch
}
}
if (participant) {
- participant->features.mute = mute;
- ast_test_suite_event_notify("CONF_MUTE", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", ast_channel_name(participant->chan), participant->features.mute ? "muted" : "unmuted", bridge->b_profile.name, ast_channel_name(participant->chan));
+ const char *state, *verb;
+
+ switch (action) {
+ case CONFBRIDGE_FEATURE_DEAFEN:
+ participant->features.deaf = 1;
+ state = "CONF_DEAF";
+ verb = "deafened";
+ break;
+ case CONFBRIDGE_FEATURE_UNDEAFEN:
+ participant->features.deaf = 0;
+ state = "CONF_DEAF";
+ verb = "undeafened";
+ break;
+ case CONFBRIDGE_FEATURE_MUTE:
+ participant->features.mute = 1;
+ state = "CONF_MUTE";
+ verb = "muted";
+ break;
+ case CONFBRIDGE_FEATURE_UNMUTE:
+ default:
+ participant->features.mute = 0;
+ state = "CONF_MUTE";
+ verb = "unmuted";
+ break;
+ }
+
+ if (state != NULL && verb != NULL) {
+ ast_test_suite_event_notify(state,
+ "Message: participant %s %s\r\n"
+ "Conference: %s\r\n"
+ "Channel: %s",
+ ast_channel_name(participant->chan),
+ verb,
+ bridge->b_profile.name,
+ ast_channel_name(participant->chan));
+ }
} else {
- res = -2;;
+ res = -2;
}
ao2_unlock(bridge);
ao2_ref(bridge, -1);
@@ -2154,9 +2245,10 @@ static int generic_mute_unmute_helper(int mute, const char *conference, const ch
return res;
}
-static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)
+static int cli_feature_action_helper(enum confbridge_feature_action action, struct ast_cli_args *a)
{
- int res = generic_mute_unmute_helper(mute, a->argv[2], a->argv[3]);
+ const char *verb;
+ int res = generic_feature_action_helper(action, a->argv[2], a->argv[3]);
if (res == -1) {
ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
@@ -2165,7 +2257,24 @@ static int cli_mute_unmute_helper(int mute, struct ast_cli_args *a)
ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]);
return -1;
}
- ast_cli(a->fd, "%s %s from confbridge %s\n", mute ? "Muting" : "Unmuting", a->argv[3], a->argv[2]);
+
+ switch (action) {
+ case CONFBRIDGE_FEATURE_DEAFEN:
+ verb = "Deafening";
+ break;
+ case CONFBRIDGE_FEATURE_UNDEAFEN:
+ verb = "Undeafening";
+ break;
+ case CONFBRIDGE_FEATURE_MUTE:
+ verb = "Muting";
+ break;
+ case CONFBRIDGE_FEATURE_UNMUTE:
+ default:
+ verb = "Unmuting";
+ break;
+ }
+
+ ast_cli(a->fd, "%s %s from confbridge %s\n", verb, a->argv[3], a->argv[2]);
return 0;
}
@@ -2187,7 +2296,7 @@ static char *handle_cli_confbridge_mute(struct ast_cli_entry *e, int cmd, struct
return CLI_SHOWUSAGE;
}
- cli_mute_unmute_helper(1, a);
+ cli_feature_action_helper(CONFBRIDGE_FEATURE_MUTE, a);
return CLI_SUCCESS;
}
@@ -2210,7 +2319,53 @@ static char *handle_cli_confbridge_unmute(struct ast_cli_entry *e, int cmd, stru
return CLI_SHOWUSAGE;
}
- cli_mute_unmute_helper(0, a);
+ cli_feature_action_helper(CONFBRIDGE_FEATURE_UNMUTE, a);
+
+ return CLI_SUCCESS;
+}
+
+static char *handle_cli_confbridge_deafen(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "confbridge deafen";
+ e->usage =
+ "Usage: confbridge deafen <conference> <channel>\n";
+ return NULL;
+ case CLI_GENERATE:
+ if (a->pos == 2) {
+ return complete_confbridge_name(a->line, a->word, a->pos, a->n);
+ }
+ return NULL;
+ }
+ if (a->argc != 4) {
+ return CLI_SHOWUSAGE;
+ }
+
+ cli_feature_action_helper(CONFBRIDGE_FEATURE_DEAFEN, a);
+
+ return CLI_SUCCESS;
+}
+
+static char *handle_cli_confbridge_undeafen(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "confbridge undeafen";
+ e->usage =
+ "Usage: confbridge undeafen <conference> <channel>\n";
+ return NULL;
+ case CLI_GENERATE:
+ if (a->pos == 2) {
+ return complete_confbridge_name(a->line, a->word, a->pos, a->n);
+ }
+ return NULL;
+ }
+ if (a->argc != 4) {
+ return CLI_SHOWUSAGE;
+ }
+
+ cli_feature_action_helper(CONFBRIDGE_FEATURE_UNDEAFEN, a);
return CLI_SUCCESS;
}
@@ -2358,6 +2513,8 @@ static struct ast_cli_entry cli_confbridge[] = {
AST_CLI_DEFINE(handle_cli_confbridge_kick, "Kick participants out of conference bridges."),
AST_CLI_DEFINE(handle_cli_confbridge_mute, "Mute a participant."),
AST_CLI_DEFINE(handle_cli_confbridge_unmute, "Unmute a participant."),
+ AST_CLI_DEFINE(handle_cli_confbridge_deafen, "Deafen a participant."),
+ AST_CLI_DEFINE(handle_cli_confbridge_undeafen, "Undeafen a participant."),
AST_CLI_DEFINE(handle_cli_confbridge_lock, "Lock a conference."),
AST_CLI_DEFINE(handle_cli_confbridge_unlock, "Unlock a conference."),
AST_CLI_DEFINE(handle_cli_confbridge_start_record, "Start recording a conference"),
@@ -2492,10 +2649,11 @@ static int action_confbridgelistrooms(struct mansession *s, const struct message
return 0;
}
-static int action_mute_unmute_helper(struct mansession *s, const struct message *m, int mute)
+static int action_feature_action_helper(struct mansession *s, const struct message *m, enum confbridge_feature_action action)
{
const char *conference = astman_get_header(m, "Conference");
const char *channel = astman_get_header(m, "Channel");
+ char *verb;
int res = 0;
if (ast_strlen_zero(conference)) {
@@ -2511,7 +2669,7 @@ static int action_mute_unmute_helper(struct mansession *s, const struct message
return 0;
}
- res = generic_mute_unmute_helper(mute, conference, channel);
+ res = generic_feature_action_helper(action, conference, channel);
if (res == -1) {
astman_send_error(s, m, "No Conference by that name found.");
@@ -2521,17 +2679,41 @@ static int action_mute_unmute_helper(struct mansession *s, const struct message
return 0;
}
- astman_send_ack(s, m, mute ? "User muted" : "User unmuted");
+ switch (action) {
+ case CONFBRIDGE_FEATURE_DEAFEN:
+ verb = "User deafened";
+ break;
+ case CONFBRIDGE_FEATURE_UNDEAFEN:
+ verb = "User undeafened";
+ break;
+ case CONFBRIDGE_FEATURE_MUTE:
+ verb = "User muted";
+ break;
+ case CONFBRIDGE_FEATURE_UNMUTE:
+ default:
+ verb = "User unmuted";
+ break;
+ }
+
+ astman_send_ack(s, m, verb);
return 0;
}
static int action_confbridgeunmute(struct mansession *s, const struct message *m)
{
- return action_mute_unmute_helper(s, m, 0);
+ return action_feature_action_helper(s, m, CONFBRIDGE_FEATURE_UNMUTE);
}
static int action_confbridgemute(struct mansession *s, const struct message *m)
{
- return action_mute_unmute_helper(s, m, 1);
+ return action_feature_action_helper(s, m, CONFBRIDGE_FEATURE_MUTE);
+}
+static int action_confbridgeundeafen(struct mansession *s, const struct message *m)
+{
+ return action_feature_action_helper(s, m, CONFBRIDGE_FEATURE_UNDEAFEN);
+}
+static int action_confbridgedeafen(struct mansession *s, const struct message *m)
+{
+ return action_feature_action_helper(s, m, CONFBRIDGE_FEATURE_DEAFEN);
}
static int action_lock_unlock_helper(struct mansession *s, const struct message *m, int lock)
@@ -2818,6 +3000,8 @@ static int unload_module(void)
res |= ast_manager_unregister("ConfbridgeListRooms");
res |= ast_manager_unregister("ConfbridgeMute");
res |= ast_manager_unregister("ConfbridgeUnmute");
+ res |= ast_manager_unregister("ConfbridgeDeafen");
+ res |= ast_manager_unregister("ConfbridgeUndeafen");
res |= ast_manager_unregister("ConfbridgeKick");
res |= ast_manager_unregister("ConfbridgeUnlock");
res |= ast_manager_unregister("ConfbridgeLock");
@@ -2860,6 +3044,8 @@ static int load_module(void)
res |= ast_manager_register_xml("ConfbridgeListRooms", EVENT_FLAG_REPORTING, action_confbridgelistrooms);
res |= ast_manager_register_xml("ConfbridgeMute", EVENT_FLAG_CALL, action_confbridgemute);
res |= ast_manager_register_xml("ConfbridgeUnmute", EVENT_FLAG_CALL, action_confbridgeunmute);
+ res |= ast_manager_register_xml("ConfbridgeDeafen", EVENT_FLAG_CALL, action_confbridgedeafen);
+ res |= ast_manager_register_xml("ConfbridgeUndeafen", EVENT_FLAG_CALL, action_confbridgeundeafen);
res |= ast_manager_register_xml("ConfbridgeKick", EVENT_FLAG_CALL, action_confbridgekick);
res |= ast_manager_register_xml("ConfbridgeUnlock", EVENT_FLAG_CALL, action_confbridgeunlock);
res |= ast_manager_register_xml("ConfbridgeLock", EVENT_FLAG_CALL, action_confbridgelock);
diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c
index f4a9604..8a02de7 100644
--- a/apps/confbridge/conf_config_parser.c
+++ b/apps/confbridge/conf_config_parser.c
@@ -279,6 +279,10 @@ static int set_sound(const char *sound_name, const char *sound_file, struct brid
ast_string_field_set(sounds, muted, sound_file);
} else if (!strcasecmp(sound_name, "sound_unmuted")) {
ast_string_field_set(sounds, unmuted, sound_file);
+ } else if (!strcasecmp(sound_name, "sound_deafened")) {
+ ast_string_field_set(sounds, deafened, sound_file);
+ } else if (!strcasecmp(sound_name, "sound_undeafened")) {
+ ast_string_field_set(sounds, undeafened, sound_file);
} else if (!strcasecmp(sound_name, "sound_there_are")) {
ast_string_field_set(sounds, thereare, sound_file);
} else if (!strcasecmp(sound_name, "sound_other_in_party")) {
@@ -418,6 +422,7 @@ static int add_action_to_menu_entry(struct conf_menu_entry *menu_entry, enum con
switch (id) {
case MENU_ACTION_NOOP:
case MENU_ACTION_TOGGLE_MUTE:
+ case MENU_ACTION_TOGGLE_DEAF:
case MENU_ACTION_INCREASE_LISTENING:
case MENU_ACTION_DECREASE_LISTENING:
case MENU_ACTION_INCREASE_TALKING:
@@ -708,6 +713,9 @@ static char *handle_cli_confbridge_show_user_profile(struct ast_cli_entry *e, in
ast_cli(a->fd,"Start Muted: %s\n",
u_profile.flags & USER_OPT_STARTMUTED?
"true" : "false");
+ ast_cli(a->fd,"Start Deaf: %s\n",
+ u_profile.flags & USER_OPT_STARTDEAF?
+ "true" : "false");
ast_cli(a->fd,"MOH When Empty: %s\n",
u_profile.flags & USER_OPT_MUSICONHOLD ?
"enabled" : "disabled");
@@ -896,6 +904,8 @@ static char *handle_cli_confbridge_show_bridge_profile(struct ast_cli_entry *e,
ast_cli(a->fd,"sound_kicked: %s\n", conf_get_sound(CONF_SOUND_KICKED, b_profile.sounds));
ast_cli(a->fd,"sound_muted: %s\n", conf_get_sound(CONF_SOUND_MUTED, b_profile.sounds));
ast_cli(a->fd,"sound_unmuted: %s\n", conf_get_sound(CONF_SOUND_UNMUTED, b_profile.sounds));
+ ast_cli(a->fd,"sound_deafened: %s\n", conf_get_sound(CONF_SOUND_DEAFENED, b_profile.sounds));
+ ast_cli(a->fd,"sound_undeafened: %s\n", conf_get_sound(CONF_SOUND_UNDEAFENED, b_profile.sounds));
ast_cli(a->fd,"sound_there_are: %s\n", conf_get_sound(CONF_SOUND_THERE_ARE, b_profile.sounds));
ast_cli(a->fd,"sound_other_in_party: %s\n", conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, b_profile.sounds));
ast_cli(a->fd,"sound_place_into_conference: %s\n", conf_get_sound(CONF_SOUND_PLACE_IN_CONF, b_profile.sounds));
@@ -1021,6 +1031,9 @@ static char *handle_cli_confbridge_show_menu(struct ast_cli_entry *e, int cmd, s
case MENU_ACTION_TOGGLE_MUTE:
ast_cli(a->fd, "toggle_mute");
break;
+ case MENU_ACTION_TOGGLE_DEAF:
+ ast_cli(a->fd, "toggle_deaf");
+ break;
case MENU_ACTION_NOOP:
ast_cli(a->fd, "no_op");
break;
@@ -1268,6 +1281,7 @@ int conf_load_config(int reload)
aco_option_register(&cfg_info, "admin", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_ADMIN);
aco_option_register(&cfg_info, "marked", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_MARKEDUSER);
aco_option_register(&cfg_info, "startmuted", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_STARTMUTED);
+ aco_option_register(&cfg_info, "startdeaf", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_STARTDEAF);
aco_option_register(&cfg_info, "music_on_hold_when_empty", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_MUSICONHOLD);
aco_option_register(&cfg_info, "quiet", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_QUIET);
aco_option_register_custom(&cfg_info, "announce_user_count_all", ACO_EXACT, user_types, "no", announce_user_count_all_handler, 0);
diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h
index d3ead35..3d773c5 100644
--- a/apps/confbridge/include/confbridge.h
+++ b/apps/confbridge/include/confbridge.h
@@ -57,6 +57,7 @@ enum user_profile_flags {
USER_OPT_DTMF_PASS = (1 << 13), /*!< Sets if dtmf should be passed into the conference or not */
USER_OPT_ANNOUNCEUSERCOUNTALL = (1 << 14), /*!< Sets if the number of users should be announced to everyone. */
USER_OPT_JITTERBUFFER = (1 << 15), /*!< Places a jitterbuffer on the user. */
+ USER_OPT_STARTDEAF = (1 << 16), /*!< Set if the caller should be initially set deaf */
};
enum bridge_profile_flags {
@@ -68,6 +69,7 @@ enum bridge_profile_flags {
enum conf_menu_action_id {
MENU_ACTION_TOGGLE_MUTE = 1,
+ MENU_ACTION_TOGGLE_DEAF,
MENU_ACTION_PLAYBACK,
MENU_ACTION_PLAYBACK_AND_CONTINUE,
MENU_ACTION_INCREASE_LISTENING,
@@ -142,6 +144,8 @@ enum conf_sounds {
CONF_SOUND_KICKED,
CONF_SOUND_MUTED,
CONF_SOUND_UNMUTED,
+ CONF_SOUND_DEAFENED,
+ CONF_SOUND_UNDEAFENED,
CONF_SOUND_ONLY_ONE,
CONF_SOUND_THERE_ARE,
CONF_SOUND_OTHER_IN_PARTY,
@@ -168,6 +172,8 @@ struct bridge_profile_sounds {
AST_STRING_FIELD(kicked);
AST_STRING_FIELD(muted);
AST_STRING_FIELD(unmuted);
+ AST_STRING_FIELD(deafened);
+ AST_STRING_FIELD(undeafened);
AST_STRING_FIELD(onlyone);
AST_STRING_FIELD(thereare);
AST_STRING_FIELD(otherinparty);
diff --git a/bridges/bridge_multiplexed.c b/bridges/bridge_multiplexed.c
index cd30266..190f790 100644
--- a/bridges/bridge_multiplexed.c
+++ b/bridges/bridge_multiplexed.c
@@ -386,7 +386,7 @@ static enum ast_bridge_write_result multiplexed_bridge_write(struct ast_bridge *
}
if (other->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
- ast_write(other->chan, frame);
+ ast_bridge_handle_channel_write(bridge, other, frame);
}
return AST_BRIDGE_WRITE_SUCCESS;
diff --git a/bridges/bridge_simple.c b/bridges/bridge_simple.c
index 69e4114..1623ce0 100644
--- a/bridges/bridge_simple.c
+++ b/bridges/bridge_simple.c
@@ -81,7 +81,7 @@ static enum ast_bridge_write_result simple_bridge_write(struct ast_bridge *bridg
/* Write the frame out if they are in the waiting state... don't worry about freeing it, the bridging core will take care of it */
if (other->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
- ast_write(other->chan, frame);
+ ast_bridge_handle_channel_write(bridge, other, frame);
}
return AST_BRIDGE_WRITE_SUCCESS;
diff --git a/bridges/bridge_softmix.c b/bridges/bridge_softmix.c
index 52e5551..5754e41 100644
--- a/bridges/bridge_softmix.c
+++ b/bridges/bridge_softmix.c
@@ -435,7 +435,7 @@ static void softmix_pass_dtmf(struct ast_bridge *bridge, struct ast_bridge_chann
if (tmp == bridge_channel) {
continue;
}
- ast_write(tmp->chan, frame);
+ ast_bridge_handle_channel_write(bridge, tmp, frame);
}
}
@@ -447,7 +447,7 @@ static void softmix_pass_video_top_priority(struct ast_bridge *bridge, struct as
continue;
}
if (ast_bridge_is_video_src(bridge, tmp->chan) == 1) {
- ast_write(tmp->chan, frame);
+ ast_bridge_handle_channel_write(bridge, tmp, frame);
break;
}
}
@@ -463,7 +463,7 @@ static void softmix_pass_video_all(struct ast_bridge *bridge, struct ast_bridge_
if ((tmp->chan == bridge_channel->chan) && !echo) {
continue;
}
- ast_write(tmp->chan, frame);
+ ast_bridge_handle_channel_write(bridge, tmp, frame);
}
}
@@ -563,7 +563,7 @@ static enum ast_bridge_write_result softmix_bridge_write(struct ast_bridge *brid
/* If a frame is ready to be written out, do so */
if (sc->have_frame) {
- ast_write(bridge_channel->chan, &sc->write_frame);
+ ast_bridge_handle_channel_write(bridge, bridge_channel, &sc->write_frame);
sc->have_frame = 0;
}
@@ -582,7 +582,7 @@ bridge_write_cleanup:
* the conference to the channel. */
ast_mutex_lock(&sc->lock);
if (sc->have_frame) {
- ast_write(bridge_channel->chan, &sc->write_frame);
+ ast_bridge_handle_channel_write(bridge, bridge_channel, &sc->write_frame);
sc->have_frame = 0;
}
ast_mutex_unlock(&sc->lock);
@@ -598,7 +598,7 @@ static int softmix_bridge_poke(struct ast_bridge *bridge, struct ast_bridge_chan
ast_mutex_lock(&sc->lock);
if (sc->have_frame) {
- ast_write(bridge_channel->chan, &sc->write_frame);
+ ast_bridge_handle_channel_write(bridge, bridge_channel, &sc->write_frame);
sc->have_frame = 0;
}
@@ -850,16 +850,24 @@ static int softmix_bridge_thread(struct ast_bridge *bridge)
ast_mutex_lock(&sc->lock);
- /* Make SLINEAR write frame from local buffer */
- if (sc->write_frame.subclass.format.id != cur_slin_id) {
- ast_format_set(&sc->write_frame.subclass.format, cur_slin_id, 0);
+ if (bridge->features.deaf ||
+ (bridge_channel->features && bridge_channel->features->deaf)) {
+ /* For deaf channels post a null frame */
+ sc->write_frame.frametype = AST_FRAME_NULL;
+ } else {
+ /* Make SLINEAR write frame from local buffer */
+ sc->write_frame.frametype = AST_FRAME_VOICE;
+ if (sc->write_frame.subclass.format.id != cur_slin_id) {
+ ast_format_set(&sc->write_frame.subclass.format, cur_slin_id, 0);
+ }
+ sc->write_frame.datalen = softmix_datalen;
+ sc->write_frame.samples = softmix_samples;
+ memcpy(sc->final_buf, buf, softmix_datalen);
+
+ /* process the softmix channel's new write audio */
+ softmix_process_write_audio(&trans_helper,
+ ast_channel_rawwriteformat(bridge_channel->chan), sc);
}
- sc->write_frame.datalen = softmix_datalen;
- sc->write_frame.samples = softmix_samples;
- memcpy(sc->final_buf, buf, softmix_datalen);
-
- /* process the softmix channel's new write audio */
- softmix_process_write_audio(&trans_helper, ast_channel_rawwriteformat(bridge_channel->chan), sc);
/* The frame is now ready for use... */
sc->have_frame = 1;
diff --git a/configs/confbridge.conf.sample b/configs/confbridge.conf.sample
index 7484b28..3b0ce85 100644
--- a/configs/confbridge.conf.sample
+++ b/configs/confbridge.conf.sample
@@ -16,6 +16,7 @@ type=user
;admin=yes ; Sets if the user is an admin or not. Off by default.
;marked=yes ; Sets if this is a marked user or not. Off by default.
;startmuted=yes; Sets if all users should start out muted. Off by default
+;startdeaf=yes ; Sets if all users should start out deaf. Off by default.
;music_on_hold_when_empty=yes ; Sets whether MOH should be played when only
; one person is in the conference or when the
; the user is waiting on a marked user to enter
@@ -210,6 +211,8 @@ type=bridge
;sound_kicked ; The sound played to a user who has been kicked from the conference.
;sound_muted ; The sound played when the mute option it toggled on.
;sound_unmuted ; The sound played when the mute option it toggled off.
+;sound_deafened ; The sound played when the deaf option is toggled on.
+;sound_undeafened ; The sound played when the deaf option is toggled off.
;sound_only_person ; The sound played when the user is the only person in the conference.
;sound_only_one ; The sound played to a user when there is only one other
; person is in the conference.
@@ -264,6 +267,8 @@ type=bridge
; toggle_mute ; Toggle turning on and off mute. Mute will make the user silent
; to everyone else, but the user will still be able to listen in.
; continue to collect the dtmf sequence.
+; toggle_deaf ; Toggle turning on and off deaf. Deaf will make the user to hear
+ ; only silence, but the user will still be able to talk.
; no_op ; This action does nothing (No Operation). Its only real purpose exists for
; being able to reserve a sequence in the config as a menu exit sequence.
; decrease_listening_volume ; Decreases the channel's listening volume.
diff --git a/include/asterisk/bridging_features.h b/include/asterisk/bridging_features.h
index e377ca6..5ce3d56 100644
--- a/include/asterisk/bridging_features.h
+++ b/include/asterisk/bridging_features.h
@@ -127,6 +127,8 @@ struct ast_bridge_features {
unsigned int usable:1;
/*! Bit to indicate whether the channel/bridge is muted or not */
unsigned int mute:1;
+ /*! Bit to indicate whether the channel/bridge is deaf or not */
+ unsigned int deaf:1;
/*! Bit to indicate whether DTMF should be passed into the bridge tech or not. */
unsigned int dtmf_passthrough:1;
diff --git a/include/asterisk/bridging_technology.h b/include/asterisk/bridging_technology.h
index 3d2e870..1ecb4c1 100644
--- a/include/asterisk/bridging_technology.h
+++ b/include/asterisk/bridging_technology.h
@@ -143,6 +143,21 @@ int ast_bridge_technology_unregister(struct ast_bridge_technology *technology);
*/
void ast_bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_channel *chan, int outfd);
+/*! \brief Used by bridging technologies to hand off a frame to be written to a bridge_channel.
+ *
+ * \param bridge The bridge that the channel is part of.
+ * \param bridge_channel The bridge channel to which the frame is written to.
+ * \param frame The frame to write.
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
+ *
+ * \note This function is essentially a wrapper for ast_write(). The bridging core has some features associated with it
+ * that requires it to have control over how frames are written into a channel. For these features to be available, the bridging
+ * technology must use this wrapper function over ast_write when pushing a frame out a channel.
+ */
+int ast_bridge_handle_channel_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame);
+
/*! \brief Lets the bridging indicate when a bridge channel has stopped or started talking.
*
* \note All DSP functionality on the bridge has been pushed down to the lowest possible
diff --git a/main/bridging.c b/main/bridging.c
index 465d033..4f67e90 100644
--- a/main/bridging.c
+++ b/main/bridging.c
@@ -337,6 +337,28 @@ void ast_bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel
return;
}
+int ast_bridge_handle_channel_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
+{
+ if (frame->frametype == AST_FRAME_VOICE &&
+ (bridge->features.deaf ||
+ (bridge_channel->features && bridge_channel->features->deaf))) {
+ short buf[frame->samples];
+ struct ast_frame sframe = {
+ .frametype = AST_FRAME_VOICE,
+ .data.ptr = buf,
+ .samples = frame->samples,
+ .datalen = sizeof(buf),
+ };
+ ast_format_set(&sframe.subclass.format, AST_FORMAT_SLINEAR, 0);
+ memset(buf, 0, sizeof(buf));
+
+ return ast_write(bridge_channel->chan, &sframe);
+ }
+
+ return ast_write(bridge_channel->chan, frame);
+}
+
+
/*! \brief Generic thread loop, TODO: Rethink this/improve it */
static int generic_thread_loop(struct ast_bridge *bridge)
{
--
1.7.12

View File

@ -1,26 +0,0 @@
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 7569bba..24a8cec 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -30189,7 +30189,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
olddirectmediaacl = ast_free_acl_list(olddirectmediaacl);
if (!ast_strlen_zero(peer->callback)) { /* build string from peer info */
char *reg_string;
- if (ast_asprintf(&reg_string, "%s?%s:%s@%s/%s", peer->name, peer->username, !ast_strlen_zero(peer->remotesecret) ? peer->remotesecret : peer->secret, peer->tohost, peer->callback) >= 0) {
+ if (ast_asprintf(&reg_string, "%s?%s:%s:%s@%s/%s", peer->name, S_OR(peer->fromuser, peer->username), S_OR(peer->remotesecret, peer->secret), peer->username, peer->tohost, peer->callback) >= 0) {
sip_register(reg_string, 0); /* XXX TODO: count in registry_count */
ast_free(reg_string);
}
diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample
index 81ca998..812be7b 100644
--- a/configs/sip.conf.sample
+++ b/configs/sip.conf.sample
@@ -711,7 +711,7 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; A similar effect can be achieved by adding a "callbackextension" option in a peer section.
; this is equivalent to having the following line in the general section:
;
-; register => username:secret@host/callbackextension
+; register => fromuser:secret:username@host/callbackextension
;
; and more readable because you don't have to write the parameters in two places
; (note that the "port" is ignored - this is a bug that should be fixed).

View File

@ -1,91 +0,0 @@
#
# Additional options for asterisk
#
# see "asterisk -h" for a list of options
#
ASTERISK_OPTS=""
#
# User and group to run asterisk as
#
# Value: double-colon separated list of user and group, or empty to run as root:
#
#
# "asterisk:asterisk" to run as user "asterisk" and group "asterisk"
# "asterisk" to run as user "asterisk" and all groups that user "asterisk" is a member of
# ":asterisk" to run as user "root" and group "asterisk"
# "" to run as user "root" and group "root"
#
ASTERISK_USER="asterisk"
#
# Nicelevel
#
# Set the priority of the asterisk process
#
# Value: (highest) -20..19 (lowest)
#
#ASTERISK_NICE="19"
#
# Wrapper script
#
# Value: yes or no/empty
#
ASTERISK_WRAPPER="no"
############# Wrapper script settings #############
#
# Send crash notifications emails to this address
# (needs a working mail service and /usr/sbin/sendmail to do so (e.g. ssmtp))
#
# Value: Email address or empty to disable
#
#ASTERISK_NOTIFY_EMAIL="root"
#
# Send asterisk's output to this terminal
#
# Value: Full path to device node or a number
#
#ASTERISK_TTY="/dev/tty9"
#
# Start an asterisk console on the terminal specified by ASTERISK_TTY
#
# Warning! Use only for debugging, this is a potential security issue!
#
# Value: yes or no/empty
#
ASTERISK_CONSOLE="no"
#
# Maximum size of core files.
#
# Value: Size in bytes, unlimited for no limit or empty to disable.
#
#ASTERISK_CORE_SIZE="unlimited"
#
# ASTERISK_CORE_DIR
#
# Value: Directory (will be created if non-existant), default is /tmp
#
ASTERISK_CORE_DIR="/var/lib/asterisk/coredump"
#
# Max number of filedescriptors
#
# Value: Number of descriptors
#
#ASTERISK_MAX_FD="1024"
#
# Kill these tasks after asterisk crashed (ASTERISK_WRAPPER=yes only!)
#
# Warning! This will kill _ALL_ tasks with the specified names!
#
# Value: Space separated list of names in double quotes (e.g. "mpg123 mad")
#
#ASTERISK_CLEANUP_ON_CRASH="mpg123 asterisk-mpg123 mad"

View File

@ -1,251 +0,0 @@
#!/sbin/runscript
extra_started_commands="forcestop reload"
depend() {
need net
after firewall
use nscd dns zaptel mysql postgresql slapd capi
}
is_running() {
if [ -z "$(pidof asterisk)" ]; then
return 1
else
PID="$(cat /var/run/asterisk/asterisk.pid 2>/dev/null)"
for x in $(pidof asterisk); do
if [ "${x}" = "${PID}" ]; then
return 0
fi
done
fi
return 1
}
asterisk_run_loop() {
local OPTS ARGS MSG NICE=""
local result=0 signal=0
# default options
OPTS="-f" # don't fork / detach breaks wrapper script...
# filter (redundant) arguments
ARGS="$(echo "${@}" | sed -e "s:-c\|-f::g")"
# mangle yes/no options
ASTERISK_CONSOLE="$(echo ${ASTERISK_CONSOLE} | tr '[:lower:]' '[:upper:]')"
if [ -n "${ASTERISK_CORE_SIZE}" ] &&
[ "${ASTERISK_CORE_SIZE}" != "0" ]; then
ulimit -c ${ASTERISK_CORE_SIZE}
if [ -n "${ASTERISK_CORE_DIR}" ] && \
[ ! -d "${ASTERISK_CORE_DIR}" ]
then
mkdir -m750 -p "${ASTERISK_CORE_DIR}"
if [ -n "${ASTERISK_USER}" ]; then
chown -R "${ASTERISK_USER}" "${ASTERISK_CORE_DIR}"
fi
fi
ASTERISK_CORE_DIR="${ASTERISK_CORE_DIR:-/tmp}"
cd "${ASTERISK_CORE_DIR}"
echo " Core dump size : ${ASTERISK_CORE_SIZE}"
echo " Core dump location : ${ASTERISK_CORE_DIR}"
fi
if [ -n "${ASTERISK_MAX_FD}" ]; then
ulimit -n ${ASTERISK_MAX_FD}
echo " Max open filedescriptors : ${ASTERISK_MAX_FD}"
fi
if [ -n "${ASTERISK_NICE}" ]; then
echo " Nice level : ${ASTERISK_NICE}"
NICE="nice -n ${ASTERISK_NICE} --"
fi
if [ -n "${ASTERISK_NOTIFY_EMAIL}" ]; then
if [ -x /usr/sbin/sendmail ]; then
echo " Email notifications go to : ${ASTERISK_NOTIFY_EMAIL}"
else
echo " Notifications disabled, /usr/sbin/sendmail doesn't exist or is not executable!"
unset ASTERISK_NOTIFY_EMAIL
fi
fi
if [ -n "${ASTERISK_TTY}" ]; then
for x in ${ASTERISK_TTY} \
/dev/tty${ASTERISK_TTY} \
/dev/vc/${ASTERISK_TTY}
do
if [ -c "${x}" ]; then
TTY="${x}"
fi
done
[ -n "${TTY}" ] && \
echo " Messages are sent to : ${TTY}"
fi
if [ "${ASTERISK_CONSOLE}" = "YES" ] && [ -n "${TTY}" ]; then
echo " Starting Asterisk console : ${ASTERISK_CONSOLE}"
OPTS="${OPTS} -c"
fi
OPTS="${OPTS} ${ARGS}"
while :; do
if [ -n "${TTY}" ]; then
/usr/bin/stty -F ${TTY} sane
${NICE} /usr/sbin/asterisk ${OPTS} >${TTY} 2>&1 <${TTY}
result=$?
else
${NICE} /usr/sbin/asterisk ${OPTS} &>/dev/null
result=$?
fi
if [ $result -eq 0 ]; then
echo "Asterisk terminated normally"
break
else
if [ $result -gt 128 ]; then
signal=$((result - 128))
MSG="Asterisk terminated with Signal: $signal"
CORE_TARGET="core-$(date "+%Y%m%d-%h%M%s")"
local CORE_DUMPED=0
if [ -f "${ASTERISK_CORE_DIR}/core" ]; then
mv "${ASTERISK_CORE_DIR}/core" \
"${ASTERISK_CORE_DIR}/${CORE_TARGET}"
CORE_DUMPED=1
elif [ -f "${ASTERISK_CORE_DIR}/core.${PID}" ]; then
mv "${ASTERISK_CORE_DIR}/core.${PID}" \
"${ASTERISK_CORE_DIR}/${CORE_TARGET}"
CORE_DUMPED=1
fi
[ $CORE_DUMPED -eq 1 ] && \
MSG="${MSG}\n\rCore dumped: ${ASTERISK_CORE_DIR}/${CORE_TARGET}"
else
MSG="Asterisk terminated with return code: $result"
fi
# kill left-over tasks
for X in ${ASTERISK_CLEANUP_ON_CRASH}; do
kill -9 $(pidof ${X});
done
fi
[ -n "${TTY}" ] \
&& echo "${MSG}" >${TTY} \
|| echo "${MSG}"
if [ -n "${ASTERISK_NOTIFY_EMAIL}" ] && \
[ -x /usr/sbin/sendmail ]; then
echo -e -n "Subject: Asterisk crashed\n\r${MSG}\n\r" |\
/usr/sbin/sendmail "${ASTERISK_NOTIFY_EMAIL}"
fi
sleep 5
echo "Restarting Asterisk..."
done
return 0
}
start() {
local OPTS USER GROUP PID
local tmp x
if [ -n "${ASTERISK_NICE}" ]; then
if [ ${ASTERISK_NICE} -ge -20 ] && \
[ ${ASTERISK_NICE} -le 19 ]; then
OPTS="--nicelevel ${ASTERISK_NICE}"
else
eerror "Nice value must be between -20 and 19"
return 1
fi
fi
if [ -n "${ASTERISK_USER}" ]; then
USER=$(echo $ASTERISK_USER | sed 's/:.*//')
GROUP=$(echo $ASTERISK_USER | awk -F: '/.*:.*/ { print $2 }')
if [ -n "${USER}" ]; then
ASTERISK_OPTS="${ASTERISK_OPTS} -U ${USER}"
fi
if [ -n "${GROUP}" ]; then
ASTERISK_OPTS="${ASTERISK_OPTS} -G ${GROUP}"
GROUP=":${GROUP}" # make it look nice...
fi
ebegin "Starting asterisk PBX (as ${USER}${GROUP})"
else
ebegin "Starting asterisk PBX (as root)"
fi
if [ "$(echo ${ASTERISK_WRAPPER} | tr '[:upper:]' '[:lower:]')" != "yes" ]; then
start-stop-daemon --start --exec /usr/sbin/asterisk \
${OPTS} -- ${ASTERISK_OPTS}
result=$?
else
asterisk_run_loop ${ASTERISK_OPTS} 2>/dev/null &
result=$?
fi
if [ $result -eq 0 ]; then
# 2 seconds should be enough for asterisk to start
sleep 2
is_running
result=$?
fi
eend $result
}
forcestop() {
ebegin "Stopping asterisk PBX"
start-stop-daemon --stop --pidfile /var/run/asterisk/asterisk.pid
eend $?
}
stop() {
if ! is_running; then
eerror "Asterisk is not running!"
return 0
fi
ebegin "Stopping asterisk PBX now"
/usr/sbin/asterisk -r -x "core stop now" &>/dev/null
# Now we have to wait until asterisk has _really_ stopped.
sleep 1
if is_running; then
einfon "Waiting for asterisk to shutdown ."
local cnt=0
while is_running; do
cnt=`expr $cnt + 1`
if [ $cnt -gt 60 ] ; then
# Waited 120 seconds now. Fail.
echo
eend 1 "Failed."
return
fi
sleep 2
echo -n "."
done
echo
fi
eend 0
}
reload() {
if is_running; then
ebegin "Reloading asterisk configuration"
/usr/sbin/asterisk -r -x "core reload" &>/dev/null
eend $?
else
eerror "Asterisk is not running!"
fi
}

View File

@ -1,17 +0,0 @@
/var/log/asterisk/messages /var/log/asterisk/*log {
missingok
rotate 5
weekly
create 0640 asterisk asterisk
postrotate
/usr/sbin/asterisk -rx 'logger reload' > /dev/null 2> /dev/null
endscript
}
/var/log/asterisk/cdr-csv/*csv {
missingok
rotate 5
monthly
create 0640 asterisk asterisk
}

View File

@ -1,6 +0,0 @@
#!/bin/sh
adduser -S -h /var/lib/asterisk -s /bin/false -D asterisk 2>/dev/null
addgroup -S dialout 2>/dev/null
addgroup asterisk dialout 2>/dev/null
exit 0

View File

@ -1,6 +0,0 @@
#!/bin/sh
adduser -S -h /var/lib/asterisk -s /bin/false -D asterisk 2>/dev/null
addgroup -S dialout 2>/dev/null
addgroup asterisk dialout 2>/dev/null
exit 0