From: Matthew Jordan Date: Tue, 26 Feb 2013 16:19:03 +0000 (+0000) Subject: Multiple revisions 379478,382068-382069 X-Git-Tag: certified/11.2-cert1-rc1~2^2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ebf522c4afd57889344951d76f53c01bebccabf3;p=thirdparty%2Fasterisk.git Multiple revisions 379478,382068-382069 ........ r379478 | kmoore | 2013-01-18 15:46:58 -0600 (Fri, 18 Jan 2013) | 13 lines Fix regression in Confbridge user count When the restructuring work got committed to Confbridge in r375470 to fix many open issues, it caused a regression in the reported count of users when conference information was requested via CLI or manager. This corrects the user count and user information displayed when listing conference information from the CLI and manager. (closes issue ASTERISK-20938) Reported By: Timo Teras Patches: confbridge-list.patch uploaded by Timo Teras (license 5409) ........ r382068 | mjordan | 2013-02-26 09:35:05 -0600 (Tue, 26 Feb 2013) | 26 lines Clean up ConfBridge commands to account for wait_marked users When ConfBridge was refactored to better handle the concept of marked, wait_marked, and normal users co-existing in a conference (thereby implementing a state machine for the conference), the wait_marked users were put into their own list of conference participants, separate from the active users. This list is used for wait_marked users when they are waiting in a conference but no marked user has joined; normal users may have joined at this point however. There are several AMI/CLI commands that affect conference users that were not checking the wait_marked users list: * CLI/AMI commands that mute/unmute a participant. In this case, wait_marked users have to remain in their particular state and should not be affected - however, the commands would return "Channel not found" as opposed to the appropriate error condition. * CLI/AMI commands that kick a participant. An admin should always be able to kick a participant out of the conference. This patch fixes both sets of commands, and cleans up the CLI commands slightly by allowing them to complete a participant name (this was supposed to have been added, but the function call was commented out and wasn't implemented). Review: https://reviewboard.asterisk.org/r/2346/ (closes issue AST-1114) Reported by: John Bigelow Tested by: John Bigelow ........ r382069 | mjordan | 2013-02-26 09:38:05 -0600 (Tue, 26 Feb 2013) | 3 lines Fix typo in r382068 Well, that was embarrassing. Removed an '-l' that somehow got in there. ........ Merged revisions 379478,382068-382069 from http://svn.asterisk.org/svn/asterisk/branches/11 git-svn-id: https://origsvn.digium.com/svn/asterisk/certified/branches/11.2@382073 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index a89cf68dfd..81f65c4d59 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -1972,6 +1972,32 @@ int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel, return 0; } +static int kick_conference_participant(struct conference_bridge *bridge, const char *channel) +{ + struct conference_bridge_user *participant = NULL; + + ao2_lock(bridge); + AST_LIST_TRAVERSE(&bridge->active_list, participant, list) { + if (!strcasecmp(ast_channel_name(participant->chan), channel)) { + participant->kicked = 1; + ast_bridge_remove(bridge->bridge, participant->chan); + ao2_unlock(bridge); + return 0; + } + } + AST_LIST_TRAVERSE(&bridge->waiting_list, participant, list) { + if (!strcasecmp(ast_channel_name(participant->chan), channel)) { + participant->kicked = 1; + ast_bridge_remove(bridge->bridge, participant->chan); + ao2_unlock(bridge); + return 0; + } + } + ao2_unlock(bridge); + + return -1; +} + static char *complete_confbridge_name(const char *line, const char *word, int pos, int state) { int which = 0; @@ -1994,11 +2020,46 @@ static char *complete_confbridge_name(const char *line, const char *word, int po return res; } +static char *complete_confbridge_participant(const char *bridge_name, const char *line, const char *word, int pos, int state) +{ + int which = 0; + RAII_VAR(struct conference_bridge *, bridge, NULL, ao2_cleanup); + struct conference_bridge tmp; + struct conference_bridge_user *participant; + char *res = NULL; + int wordlen = strlen(word); + + ast_copy_string(tmp.name, bridge_name, sizeof(tmp.name)); + bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + if (!bridge) { + return NULL; + } + + ao2_lock(bridge); + AST_LIST_TRAVERSE(&bridge->active_list, participant, list) { + if (!strncasecmp(ast_channel_name(participant->chan), word, wordlen) && ++which > state) { + res = ast_strdup(ast_channel_name(participant->chan)); + ao2_unlock(bridge); + return res; + } + } + + AST_LIST_TRAVERSE(&bridge->waiting_list, participant, list) { + if (!strncasecmp(ast_channel_name(participant->chan), word, wordlen) && ++which > state) { + res = ast_strdup(ast_channel_name(participant->chan)); + ao2_unlock(bridge); + return res; + } + } + ao2_unlock(bridge); + + return NULL; +} + static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { struct conference_bridge *bridge = NULL; struct conference_bridge tmp; - struct conference_bridge_user *participant = NULL; switch (cmd) { case CLI_INIT: @@ -2011,11 +2072,9 @@ static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct if (a->pos == 2) { return complete_confbridge_name(a->line, a->word, a->pos, a->n); } - /* if (a->pos == 3) { - return complete_confbridge_channel(a->line, a->word, a->pos, a->n); + return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n); } - */ return NULL; } @@ -2029,22 +2088,25 @@ static char *handle_cli_confbridge_kick(struct ast_cli_entry *e, int cmd, struct ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]); return CLI_SUCCESS; } - ao2_lock(bridge); - AST_LIST_TRAVERSE(&bridge->active_list, participant, list) { - if (!strncmp(a->argv[3], ast_channel_name(participant->chan), strlen(ast_channel_name(participant->chan)))) { - break; - } - } - if (participant) { - ast_cli(a->fd, "Kicking %s from confbridge %s\n", ast_channel_name(participant->chan), bridge->name); - participant->kicked = 1; - ast_bridge_remove(bridge->bridge, participant->chan); + if (kick_conference_participant(bridge, a->argv[3])) { + ast_cli(a->fd, "No participant named '%s' found!\n", a->argv[3]); + return CLI_SUCCESS; } - ao2_unlock(bridge); ao2_ref(bridge, -1); + ast_cli(a->fd, "Participant '%s' kicked out of conference '%s'\n", a->argv[3], a->argv[2]); return CLI_SUCCESS; } +static void handle_cli_confbridge_list_item(struct ast_cli_args *a, struct conference_bridge_user *participant) +{ + ast_cli(a->fd, "%-29s ", ast_channel_name(participant->chan)); + ast_cli(a->fd, "%-17s", participant->u_profile.name); + ast_cli(a->fd, "%-17s", participant->b_profile.name); + ast_cli(a->fd, "%-17s", participant->menu_name); + ast_cli(a->fd, "%-17s", S_COR(ast_channel_caller(participant->chan)->id.number.valid, ast_channel_caller(participant->chan)->id.number.str, "")); + ast_cli(a->fd, "\n"); +} + static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { struct ao2_iterator i; @@ -2071,7 +2133,7 @@ static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli(a->fd, "================================ ====== ====== ========\n"); i = ao2_iterator_init(conference_bridges, 0); while ((bridge = ao2_iterator_next(&i))) { - ast_cli(a->fd, "%-32s %6i %6i %s\n", bridge->name, bridge->activeusers, bridge->markedusers, (bridge->locked ? "locked" : "unlocked")); + ast_cli(a->fd, "%-32s %6i %6i %s\n", bridge->name, bridge->activeusers + bridge->waitingusers, bridge->markedusers, (bridge->locked ? "locked" : "unlocked")); ao2_ref(bridge, -1); } ao2_iterator_destroy(&i); @@ -2089,12 +2151,10 @@ static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli(a->fd, "============================= ================ ================ ================ ================\n"); ao2_lock(bridge); AST_LIST_TRAVERSE(&bridge->active_list, participant, list) { - ast_cli(a->fd, "%-29s ", ast_channel_name(participant->chan)); - ast_cli(a->fd, "%-17s", participant->u_profile.name); - ast_cli(a->fd, "%-17s", participant->b_profile.name); - ast_cli(a->fd, "%-17s", participant->menu_name); - ast_cli(a->fd, "%-17s", S_COR(ast_channel_caller(participant->chan)->id.number.valid, ast_channel_caller(participant->chan)->id.number.str, "")); - ast_cli(a->fd, "\n"); + handle_cli_confbridge_list_item(a, participant); + } + AST_LIST_TRAVERSE(&bridge->waiting_list, participant, list) { + handle_cli_confbridge_list_item(a, participant); } ao2_unlock(bridge); ao2_ref(bridge, -1); @@ -2187,12 +2247,16 @@ static char *handle_cli_confbridge_mute(struct ast_cli_entry *e, int cmd, struct case CLI_INIT: e->command = "confbridge mute"; e->usage = - "Usage: confbridge mute \n"; + "Usage: confbridge mute \n" + " Mute a channel in a conference.\n"; return NULL; case CLI_GENERATE: if (a->pos == 2) { return complete_confbridge_name(a->line, a->word, a->pos, a->n); } + if (a->pos == 3) { + return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n); + } return NULL; } if (a->argc != 4) { @@ -2210,12 +2274,16 @@ static char *handle_cli_confbridge_unmute(struct ast_cli_entry *e, int cmd, stru case CLI_INIT: e->command = "confbridge unmute"; e->usage = - "Usage: confbridge unmute \n"; + "Usage: confbridge unmute \n" + " Unmute a channel in a conference.\n"; return NULL; case CLI_GENERATE: if (a->pos == 2) { return complete_confbridge_name(a->line, a->word, a->pos, a->n); } + if (a->pos == 3) { + return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n); + } return NULL; } if (a->argc != 4) { @@ -2233,7 +2301,9 @@ static char *handle_cli_confbridge_lock(struct ast_cli_entry *e, int cmd, struct case CLI_INIT: e->command = "confbridge lock"; e->usage = - "Usage: confbridge lock \n"; + "Usage: confbridge lock \n" + " Lock a conference. While locked, no new non-admins\n" + " may join the conference.\n"; return NULL; case CLI_GENERATE: if (a->pos == 2) { @@ -2258,7 +2328,8 @@ static char *handle_cli_confbridge_unlock(struct ast_cli_entry *e, int cmd, stru case CLI_INIT: e->command = "confbridge unlock"; e->usage = - "Usage: confbridge unlock \n"; + "Usage: confbridge unlock \n" + " Unlock a previously locked conference.\n"; return NULL; case CLI_GENERATE: if (a->pos == 2) { @@ -2346,7 +2417,8 @@ static char *handle_cli_confbridge_stop_record(struct ast_cli_entry *e, int cmd, case CLI_INIT: e->command = "confbridge record stop"; e->usage = - "Usage: confbridge record stop \n"; + "Usage: confbridge record stop \n" + " Stop a previously started recording.\n"; return NULL; case CLI_GENERATE: if (a->pos == 3) { @@ -2393,6 +2465,27 @@ static struct ast_custom_function confbridge_info_function = { .read = func_confbridge_info, }; +static void action_confbridgelist_item(struct mansession *s, const char *id_text, struct conference_bridge *bridge, struct conference_bridge_user *participant) +{ + astman_append(s, + "Event: ConfbridgeList\r\n" + "%s" + "Conference: %s\r\n" + "CallerIDNum: %s\r\n" + "CallerIDName: %s\r\n" + "Channel: %s\r\n" + "Admin: %s\r\n" + "MarkedUser: %s\r\n" + "\r\n", + id_text, + bridge->name, + S_COR(ast_channel_caller(participant->chan)->id.number.valid, ast_channel_caller(participant->chan)->id.number.str, ""), + S_COR(ast_channel_caller(participant->chan)->id.name.valid, ast_channel_caller(participant->chan)->id.name.str, ""), + ast_channel_name(participant->chan), + ast_test_flag(&participant->u_profile, USER_OPT_ADMIN) ? "Yes" : "No", + ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No"); +} + static int action_confbridgelist(struct mansession *s, const struct message *m) { const char *actionid = astman_get_header(m, "ActionID"); @@ -2426,23 +2519,11 @@ static int action_confbridgelist(struct mansession *s, const struct message *m) ao2_lock(bridge); AST_LIST_TRAVERSE(&bridge->active_list, participant, list) { total++; - astman_append(s, - "Event: ConfbridgeList\r\n" - "%s" - "Conference: %s\r\n" - "CallerIDNum: %s\r\n" - "CallerIDName: %s\r\n" - "Channel: %s\r\n" - "Admin: %s\r\n" - "MarkedUser: %s\r\n" - "\r\n", - id_text, - bridge->name, - S_COR(ast_channel_caller(participant->chan)->id.number.valid, ast_channel_caller(participant->chan)->id.number.str, ""), - S_COR(ast_channel_caller(participant->chan)->id.name.valid, ast_channel_caller(participant->chan)->id.name.str, ""), - ast_channel_name(participant->chan), - ast_test_flag(&participant->u_profile, USER_OPT_ADMIN) ? "Yes" : "No", - ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No"); + action_confbridgelist_item(s, id_text, bridge, participant); + } + AST_LIST_TRAVERSE(&bridge->waiting_list, participant, list) { + total++; + action_confbridgelist_item(s, id_text, bridge, participant); } ao2_unlock(bridge); ao2_ref(bridge, -1); @@ -2492,7 +2573,7 @@ static int action_confbridgelistrooms(struct mansession *s, const struct message "\r\n", id_text, bridge->name, - bridge->activeusers, + bridge->activeusers + bridge->waitingusers, bridge->markedusers, bridge->locked ? "Yes" : "No"); ao2_unlock(bridge); @@ -2586,7 +2667,6 @@ static int action_confbridgekick(struct mansession *s, const struct message *m) { const char *conference = astman_get_header(m, "Conference"); const char *channel = astman_get_header(m, "Channel"); - struct conference_bridge_user *participant = NULL; struct conference_bridge *bridge = NULL; struct conference_bridge tmp; int found = 0; @@ -2599,6 +2679,7 @@ static int action_confbridgekick(struct mansession *s, const struct message *m) astman_send_error(s, m, "No active conferences."); return 0; } + ast_copy_string(tmp.name, conference, sizeof(tmp.name)); bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); if (!bridge) { @@ -2606,16 +2687,7 @@ static int action_confbridgekick(struct mansession *s, const struct message *m) return 0; } - ao2_lock(bridge); - AST_LIST_TRAVERSE(&bridge->active_list, participant, list) { - if (!strcasecmp(ast_channel_name(participant->chan), channel)) { - participant->kicked = 1; - ast_bridge_remove(bridge->bridge, participant->chan); - found = 1; - break; - } - } - ao2_unlock(bridge); + found = !kick_conference_participant(bridge, channel); ao2_ref(bridge, -1); if (found) { @@ -2796,6 +2868,9 @@ static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char AST_LIST_TRAVERSE(&bridge->active_list, participant, list) { count++; } + AST_LIST_TRAVERSE(&bridge->waiting_list, participant, list) { + count++; + } } else if (!strncasecmp(args.type, "admins", 6)) { AST_LIST_TRAVERSE(&bridge->active_list, participant, list) { if (ast_test_flag(&participant->u_profile, USER_OPT_ADMIN)) {