aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/app_confbridge.c119
-rw-r--r--apps/app_directed_pickup.c24
-rw-r--r--apps/app_queue.c4
-rw-r--r--apps/confbridge/conf_config_parser.c12
-rw-r--r--apps/confbridge/include/confbridge.h1
5 files changed, 134 insertions, 26 deletions
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index 7cede133e..177ee3717 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -106,6 +106,22 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<para>exten => 1,n,ConfBridge(1)</para>
</description>
</function>
+ <function name="CONFBRIDGE_INFO" language="en_US">
+ <synopsis>
+ Get information about a ConfBridge conference.
+ </synopsis>
+ <syntax>
+ <parameter name="type" required="true">
+ <para>Type can be <literal>parties</literal>, <literal>admins</literal>, <literal>marked</literal>, or <literal>locked</literal>.</para>
+ </parameter>
+ <parameter name="conf" required="true">
+ <para>Conf refers to the name of the conference being referenced.</para>
+ </parameter>
+ </syntax>
+ <description>
+ <para>This function returns a non-negative integer for valid conference identifiers (0 or 1 for <literal>locked</literal>) and "" for invalid conference identifiers.</para>
+ </description>
+ </function>
<manager name="ConfbridgeList" language="en_US">
<synopsis>
List participants in a conference.
@@ -618,7 +634,8 @@ static void post_join_marked(struct conference_bridge *conference_bridge, struct
if (other_conference_bridge_user == conference_bridge_user) {
continue;
}
- if (ast_test_flag(&other_conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, other_conference_bridge_user->chan)) {
+ if (other_conference_bridge_user->playing_moh && !ast_bridge_suspend(conference_bridge->bridge, other_conference_bridge_user->chan)) {
+ other_conference_bridge_user->playing_moh = 0;
ast_moh_stop(other_conference_bridge_user->chan);
ast_bridge_unsuspend(conference_bridge->bridge, other_conference_bridge_user->chan);
}
@@ -664,6 +681,7 @@ static void post_join_marked(struct conference_bridge *conference_bridge, struct
*/
if (!conference_bridge->markedusers && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) {
ast_moh_start(conference_bridge_user->chan, conference_bridge_user->u_profile.moh_class, NULL);
+ conference_bridge_user->playing_moh = 1;
}
}
}
@@ -692,6 +710,7 @@ static void post_join_unmarked(struct conference_bridge *conference_bridge, stru
*/
if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) {
ast_moh_start(conference_bridge_user->chan, conference_bridge_user->u_profile.moh_class, NULL);
+ conference_bridge_user->playing_moh = 1;
}
return;
}
@@ -709,6 +728,7 @@ static void post_join_unmarked(struct conference_bridge *conference_bridge, stru
/* Temporarily suspend the above participant from the bridge so we have control to stop MOH if needed */
if (ast_test_flag(&first_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) {
+ first_participant->playing_moh = 0;
ast_moh_stop(first_participant->chan);
ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan);
}
@@ -924,6 +944,7 @@ static void leave_conference_bridge(struct conference_bridge *conference_bridge,
ast_bridge_remove(conference_bridge->bridge, other_participant->chan);
} else if (ast_test_flag(&other_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, other_participant->chan)) {
ast_moh_start(other_participant->chan, other_participant->u_profile.moh_class, NULL);
+ other_participant->playing_moh = 1;
ast_bridge_unsuspend(conference_bridge->bridge, other_participant->chan);
}
}
@@ -933,6 +954,7 @@ static void leave_conference_bridge(struct conference_bridge *conference_bridge,
if (ast_test_flag(&first_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) {
ast_moh_start(first_participant->chan, first_participant->u_profile.moh_class, NULL);
+ first_participant->playing_moh = 1;
ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan);
}
}
@@ -1192,14 +1214,22 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
if (args.argc > 1 && !ast_strlen_zero(args.b_profile_name)) {
b_profile_name = args.b_profile_name;
}
- conf_find_bridge_profile(chan, b_profile_name, &conference_bridge_user.b_profile);
+ if (!conf_find_bridge_profile(chan, b_profile_name, &conference_bridge_user.b_profile)) {
+ ast_log(LOG_WARNING, "Conference bridge profile %s does not exist\n", b_profile_name);
+ res = -1;
+ goto confbridge_cleanup;
+ }
/* user profile name */
if (args.argc > 2 && !ast_strlen_zero(args.u_profile_name)) {
u_profile_name = args.u_profile_name;
}
- conf_find_user_profile(chan, u_profile_name, &conference_bridge_user.u_profile);
+ if (!conf_find_user_profile(chan, u_profile_name, &conference_bridge_user.u_profile)) {
+ ast_log(LOG_WARNING, "Conference user profile %s does not exist\n", u_profile_name);
+ res = -1;
+ goto confbridge_cleanup;
+ }
quiet = ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_QUIET);
/* ask for a PIN immediately after finding user profile. This has to be
@@ -1301,7 +1331,13 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
/* Play the Join sound to both the conference and the user entering. */
if (!quiet) {
const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, conference_bridge_user.b_profile.sounds);
+ if (conference_bridge_user.playing_moh) {
+ ast_moh_stop(chan);
+ }
ast_stream_and_wait(chan, join_sound, "");
+ if (conference_bridge_user.playing_moh) {
+ ast_moh_start(chan, conference_bridge_user.u_profile.moh_class, NULL);
+ }
ast_autoservice_start(chan);
play_sound_file(conference_bridge, join_sound);
ast_autoservice_stop(chan);
@@ -1635,8 +1671,8 @@ int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel,
/* See if music on hold is playing */
ao2_lock(conference_bridge);
- if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) {
- /* Just us so MOH is probably indeed going, let's stop it */
+ if (conference_bridge_user->playing_moh) {
+ /* MOH is going, let's stop it */
ast_moh_stop(bridge_channel->chan);
}
ao2_unlock(conference_bridge);
@@ -1646,7 +1682,7 @@ int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel,
/* See if music on hold needs to be started back up again */
ao2_lock(conference_bridge);
- if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) {
+ if (conference_bridge_user->playing_moh) {
ast_moh_start(bridge_channel->chan, conference_bridge_user->u_profile.moh_class, NULL);
}
ao2_unlock(conference_bridge);
@@ -2059,6 +2095,12 @@ static struct ast_custom_function confbridge_function = {
.write = func_confbridge_helper,
};
+static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
+static struct ast_custom_function confbridge_info_function = {
+ .name = "CONFBRIDGE_INFO",
+ .read = func_confbridge_info,
+};
+
static int action_confbridgelist(struct mansession *s, const struct message *m)
{
const char *actionid = astman_get_header(m, "ActionID");
@@ -2370,7 +2412,68 @@ static int action_confbridgestoprecord(struct mansession *s, const struct messag
return 0;
}
+static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+{
+ char *parse = NULL;
+ struct conference_bridge *bridge = NULL;
+ struct conference_bridge_user *participant = NULL;
+ struct conference_bridge tmp;
+ int count = 0;
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(type);
+ AST_APP_ARG(confno);
+ );
+ /* parse all the required arguments and make sure they exist. */
+ if (ast_strlen_zero(data)) {
+ return -1;
+ }
+ parse = ast_strdupa(data);
+ AST_STANDARD_APP_ARGS(args, parse);
+ if (ast_strlen_zero(args.confno) || ast_strlen_zero(args.type)) {
+ return -1;
+ }
+ if (!ao2_container_count(conference_bridges)) {
+ ast_log(LOG_ERROR, "No active conferneces.\n");
+ return -1;
+ }
+ ast_copy_string(tmp.name, args.confno, sizeof(tmp.name));
+ bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER);
+ if (!bridge) {
+ ast_log(LOG_ERROR, "Confernece '%s' not found.\n", args.confno);
+ return -1;
+ }
+
+ /* get the correct count for the type requested */
+ ao2_lock(bridge);
+ if (!strncasecmp(args.type, "parties", 7)) {
+ AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
+ count++;
+ }
+ } else if (!strncasecmp(args.type, "admins", 6)) {
+ AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
+ if (ast_test_flag(&participant->u_profile, USER_OPT_ADMIN)) {
+ count++;
+ }
+ }
+ } else if (!strncasecmp(args.type, "marked", 6)) {
+ AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
+ if (ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER)) {
+ count++;
+ }
+ }
+ } else if (!strncasecmp(args.type, "locked", 6)) {
+ count = bridge->locked;
+ } else {
+ ao2_unlock(bridge);
+ ao2_ref(bridge, -1);
+ return -1;
+ }
+ snprintf(buf, len, "%d", count);
+ ao2_unlock(bridge);
+ ao2_ref(bridge, -1);
+ return 0;
+}
/*! \brief Called when module is being unloaded */
static int unload_module(void)
@@ -2378,6 +2481,7 @@ static int unload_module(void)
int res = ast_unregister_application(app);
ast_custom_function_unregister(&confbridge_function);
+ ast_custom_function_unregister(&confbridge_info_function);
ast_cli_unregister_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry));
@@ -2409,6 +2513,9 @@ static int load_module(void)
if ((ast_custom_function_register(&confbridge_function))) {
return AST_MODULE_LOAD_FAILURE;
}
+ if ((ast_custom_function_register(&confbridge_info_function))) {
+ return AST_MODULE_LOAD_FAILURE;
+ }
if (!(record_tech.capabilities = ast_format_cap_alloc())) {
return AST_MODULE_LOAD_FAILURE;
}
diff --git a/apps/app_directed_pickup.c b/apps/app_directed_pickup.c
index 38f24effc..63a7621ff 100644
--- a/apps/app_directed_pickup.c
+++ b/apps/app_directed_pickup.c
@@ -97,19 +97,6 @@ static const char app[] = "Pickup";
static const char app2[] = "PickupChan";
/*! \todo This application should return a result code, like PICKUPRESULT */
-/* Helper function that determines whether a channel is capable of being picked up */
-static int can_pickup(struct ast_channel *chan)
-{
- if (!chan->pbx && !chan->masq &&
- !ast_test_flag(chan, AST_FLAG_ZOMBIE) &&
- (chan->_state == AST_STATE_RINGING ||
- chan->_state == AST_STATE_RING ||
- chan->_state == AST_STATE_DOWN)) {
- return 1;
- }
- return 0;
-}
-
struct pickup_by_name_args {
const char *name;
size_t len;
@@ -121,7 +108,7 @@ static int pickup_by_name_cb(void *obj, void *arg, void *data, int flags)
struct pickup_by_name_args *args = data;
ast_channel_lock(target);
- if (!strncasecmp(target->name, args->name, args->len) && can_pickup(target)) {
+ if (!strncasecmp(target->name, args->name, args->len) && ast_can_pickup(target)) {
/* Return with the channel still locked on purpose */
return CMP_MATCH | CMP_STOP;
}
@@ -190,7 +177,7 @@ static int pickup_by_exten(struct ast_channel *chan, const char *exten, const ch
while ((target = ast_channel_iterator_next(iter))) {
ast_channel_lock(target);
- if ((chan != target) && can_pickup(target)) {
+ if ((chan != target) && ast_can_pickup(target)) {
ast_log(LOG_NOTICE, "%s pickup by %s\n", target->name, chan->name);
break;
}
@@ -217,7 +204,7 @@ static int find_by_mark(void *obj, void *arg, void *data, int flags)
ast_channel_lock(target);
tmp = pbx_builtin_getvar_helper(target, PICKUPMARK);
- if (tmp && !strcasecmp(tmp, mark) && can_pickup(target)) {
+ if (tmp && !strcasecmp(tmp, mark) && ast_can_pickup(target)) {
/* Return with the channel still locked on purpose */
return CMP_MATCH | CMP_STOP;
}
@@ -249,7 +236,8 @@ static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
struct ast_channel *chan = data;/*!< Channel wanting to pickup call */
ast_channel_lock(target);
- if (chan != target && (chan->pickupgroup & target->callgroup) && can_pickup(target)) {
+ if (chan != target && (chan->pickupgroup & target->callgroup)
+ && ast_can_pickup(target)) {
/* Return with the channel still locked on purpose */
return CMP_MATCH | CMP_STOP;
}
@@ -316,7 +304,7 @@ static int find_by_part(void *obj, void *arg, void *data, int flags)
ast_channel_lock(target);
if (len <= strlen(target->name) && !strncmp(target->name, part, len)
- && can_pickup(target)) {
+ && ast_can_pickup(target)) {
/* Return with the channel still locked on purpose */
return CMP_MATCH | CMP_STOP;
}
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 146cf63d6..be929c1dc 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -3482,7 +3482,9 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
if (o->stillgoing) { /* Keep track of important channels */
stillgoing = 1;
if (o->chan) {
- watchers[pos++] = o->chan;
+ if (pos < AST_MAX_WATCHERS) {
+ watchers[pos++] = o->chan;
+ }
if (!start)
start = o;
else
diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c
index dbec32bba..3d1f31326 100644
--- a/apps/confbridge/conf_config_parser.c
+++ b/apps/confbridge/conf_config_parser.c
@@ -582,7 +582,7 @@ static int add_action_to_menu_entry(struct conf_menu_entry *menu_entry, enum con
static int add_menu_entry(struct conf_menu *menu, const char *dtmf, const char *action_names)
{
- struct conf_menu_entry *menu_entry = NULL;
+ struct conf_menu_entry *menu_entry = NULL, *cur = NULL;
int res = 0;
char *tmp_action_names = ast_strdupa(action_names);
char *action = NULL;
@@ -691,6 +691,16 @@ static int add_menu_entry(struct conf_menu *menu, const char *dtmf, const char *
return -1;
}
+ /* remove any list entry with an identical DTMF sequence for overrides */
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&menu->entries, cur, entry) {
+ if (!strcasecmp(cur->dtmf, menu_entry->dtmf)) {
+ AST_LIST_REMOVE_CURRENT(entry);
+ ast_free(cur);
+ break;
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+
AST_LIST_INSERT_TAIL(&menu->entries, menu_entry, entry);
return 0;
diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h
index 4b6c0615e..de467b5f7 100644
--- a/apps/confbridge/include/confbridge.h
+++ b/apps/confbridge/include/confbridge.h
@@ -215,6 +215,7 @@ struct conference_bridge_user {
struct ast_bridge_features features; /*!< Bridge features structure */
struct ast_bridge_tech_optimizations tech_args; /*!< Bridge technology optimizations for talk detection */
unsigned int kicked:1; /*!< User has been kicked from the conference */
+ unsigned int playing_moh:1; /*!< MOH is currently being played to the user */
AST_LIST_ENTRY(conference_bridge_user) list; /*!< Linked list information */
};