]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Multiple revisions 379478,382068-382069
authorMatthew Jordan <mjordan@digium.com>
Tue, 26 Feb 2013 16:19:03 +0000 (16:19 +0000)
committerMatthew Jordan <mjordan@digium.com>
Tue, 26 Feb 2013 16:19:03 +0000 (16:19 +0000)
........
  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

apps/app_confbridge.c

index a89cf68dfd565595491eb74cb108ad5828da9544..81f65c4d598dc03c3f90e707402259cb842a1ef7 100644 (file)
@@ -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, "<unknown>"));
+       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, "<unknown>"));
-                       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 <conference> <channel>\n";
+                       "Usage: confbridge mute <conference> <channel>\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 <conference> <channel>\n";
+                       "Usage: confbridge unmute <conference> <channel>\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 <conference>\n";
+                       "Usage: confbridge lock <conference>\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 <conference>\n";
+                       "Usage: confbridge unlock <conference>\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 <conference>\n";
+                       "Usage: confbridge record stop <conference>\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, "<unknown>"),
+               S_COR(ast_channel_caller(participant->chan)->id.name.valid, ast_channel_caller(participant->chan)->id.name.str, "<no name>"),
+               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, "<unknown>"),
-                       S_COR(ast_channel_caller(participant->chan)->id.name.valid, ast_channel_caller(participant->chan)->id.name.str, "<no name>"),
-                       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)) {