return 0;
}
+static int kick_conference_participant(struct conference_bridge *bridge, const char *channel)
+{
+ struct conference_bridge_user *participant = NULL;
+
+ SCOPED_AO2LOCK(bridge_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);
+ 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);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
static char *complete_confbridge_name(const char *line, const char *word, int pos, int state)
{
int which = 0;
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;
+ }
+
+ {
+ SCOPED_AO2LOCK(bridge_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));
+ 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));
+ return res;
+ }
+ }
+ }
+
+ 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:
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;
}
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;
}
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) {
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) {
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) {
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) {
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) {
{
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;
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) {
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) {
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)) {