From a0486afb833b715fad3b31833bd7d2348f5fe6e1 Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Sat, 22 May 2004 04:11:22 +0000 Subject: [PATCH] Merge fabeman's extensive meetme improvements (bug #1624) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3038 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/app_meetme.c | 567 +++++++++++++++++++++++++++++++++--- channel.c | 13 + include/asterisk/channel.h | 3 + manager.c | 15 +- sounds.txt | 18 ++ sounds/conf-adminmenu.gsm | Bin 0 -> 11187 bytes sounds/conf-errormenu.gsm | Bin 0 -> 2376 bytes sounds/conf-kicked.gsm | Bin 0 -> 3861 bytes sounds/conf-locked.gsm | Bin 0 -> 2805 bytes sounds/conf-lockednow.gsm | Bin 0 -> 3597 bytes sounds/conf-muted.gsm | Bin 0 -> 2178 bytes sounds/conf-unlockednow.gsm | Bin 0 -> 4290 bytes sounds/conf-unmuted.gsm | Bin 0 -> 2607 bytes sounds/conf-usermenu.gsm | Bin 0 -> 5016 bytes 14 files changed, 573 insertions(+), 43 deletions(-) create mode 100755 sounds/conf-adminmenu.gsm create mode 100755 sounds/conf-errormenu.gsm create mode 100755 sounds/conf-kicked.gsm create mode 100755 sounds/conf-locked.gsm create mode 100755 sounds/conf-lockednow.gsm create mode 100755 sounds/conf-muted.gsm create mode 100755 sounds/conf-unlockednow.gsm create mode 100755 sounds/conf-unmuted.gsm create mode 100755 sounds/conf-usermenu.gsm diff --git a/apps/app_meetme.c b/apps/app_meetme.c index 2b77c0f686..7dacfc57eb 100755 --- a/apps/app_meetme.c +++ b/apps/app_meetme.c @@ -38,9 +38,11 @@ static char *tdesc = "Simple MeetMe conference bridge"; static char *app = "MeetMe"; static char *app2 = "MeetMeCount"; +static char *app3 = "MeetMeAdmin"; static char *synopsis = "Simple MeetMe conference bridge"; static char *synopsis2 = "MeetMe participant count"; +static char *synopsis3 = "Send Admin Commands to a conference"; static char *descrip = " MeetMe(confno[,[options][,pin]]): Enters the user into a specified MeetMe conference.\n" @@ -59,11 +61,11 @@ static char *descrip = " 'v' -- video mode\n" " 'q' -- quiet mode (don't play enter/leave sounds)\n" " 'M' -- enable music on hold when the conference has a single caller\n" +" 'x' -- exit the conference if the last marked user left\n" " 'b' -- run AGI script specified in ${MEETME_AGI_BACKGROUND}\n" " Default: conf-background.agi\n" " (Note: This does not work with non-Zap channels in the same conference)\n" -" Not implemented yet:\n" -" 's' -- send user to admin/user menu if '*' is received\n" +" 'u' -- send user to admin/user menu if '*' is received\n" " 'a' -- set admin mode\n"; static char *descrip2 = @@ -72,6 +74,8 @@ static char *descrip2 = "will be returned in the variable. Returns 0 on success or -1 on a hangup.\n" "A ZAPTEL INTERFACE MUST BE INSTALLED FOR CONFERENCING FUNCTIONALITY.\n"; +static char *descrip3 = ""; + STANDARD_LOCAL_USER; LOCAL_USER_DECL; @@ -81,14 +85,35 @@ static struct ast_conference { int fd; /* Announcements fd */ int zapconf; /* Zaptel Conf # */ int users; /* Number of active users */ + int markedusers; /* Number of marked users */ + struct ast_conf_user *firstuser; /* Pointer to the first user struct */ + struct ast_conf_user *lastuser; /* Pointer to the last user struct */ time_t start; /* Start time (s) */ int isdynamic; /* Created on the fly? */ + int locked; /* Is the conference locked? */ char pin[AST_MAX_EXTENSION]; /* If protected by a PIN */ struct ast_conference *next; } *confs; +struct ast_conf_user { + int user_no; /* User Number */ + struct ast_conf_user *prevuser; /* Pointer to the previous user */ + struct ast_conf_user *nextuser; /* Pointer to the next user */ + int userflags; /* Flags as set in the conference */ + int adminflags; /* Flags set by the Admin */ + struct ast_channel *chan; /* Connected channel */ + char usrvalue[50]; /* Custom User Value */ + time_t jointime; /* Time the user joined the conference */ +}; + +#define ADMINFLAG_MUTED (1 << 1) /* User is muted */ +#define ADMINFLAG_KICKME (1 << 2) /* User is kicked */ + + static ast_mutex_t conflock = AST_MUTEX_INITIALIZER; +static int admin_exec(struct ast_channel *chan, void *data); + #include "enter.h" #include "leave.h" @@ -106,6 +131,7 @@ static ast_mutex_t conflock = AST_MUTEX_INITIALIZER; #define CONFFLAG_VIDEO (1 << 7) /* Set to enable video mode */ #define CONFFLAG_AGI (1 << 8) /* Set to run AGI Script in Background */ #define CONFFLAG_MOH (1 << 9) /* Set to have music on hold when */ +#define CONFFLAG_ADMINEXIT (1 << 10) /* If set the MeetMe will return if all marked with this flag left */ static int careful_write(int fd, unsigned char *data, int len) @@ -186,9 +212,13 @@ static struct ast_conference *build_conf(char *confno, char *pin, int make, int cnf = NULL; goto cnfout; } + /* Fill the conference struct */ cnf->start = time(NULL); cnf->zapconf = ztc.confno; cnf->isdynamic = dynamic; + cnf->firstuser = NULL; + cnf->lastuser = NULL; + cnf->locked = 0; if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Created ZapTel conference %d for conference '%s'\n", cnf->zapconf, cnf->confno); cnf->next = confs; @@ -203,48 +233,209 @@ cnfout: static int confs_show(int fd, int argc, char **argv) { - struct ast_conference *conf; + ast_cli(fd, "Deprecated! Please use 'meetme' instead.\n"); + return RESULT_SUCCESS; +} + +static char show_confs_usage[] = +"Deprecated! Please use 'meetme' instead.\n"; + +static struct ast_cli_entry cli_show_confs = { + { "show", "conferences", NULL }, confs_show, + "Show status of conferences", show_confs_usage, NULL }; + +static int conf_cmd(int fd, int argc, char **argv) { + /* Process the command */ + struct ast_conference *cnf; + struct ast_conf_user *user; int hr, min, sec; + int i = 0; time_t now; char *header_format = "%-14s %-14s %-8s %-8s\n"; char *data_format = "%-12.12s %4.4d %02d:%02d:%02d %-8s\n"; - + char cmdline[1024] = ""; + if (argc > 8) + ast_cli(fd, "Invalid Arguments.\n"); + /* Check for length so no buffer will overflow... */ + for (i = 0; i < argc; i++) { + if (strlen(argv[i]) > 100) + ast_cli(fd, "Invalid Arguments.\n"); + } + if (argc == 1) { + /* List all the conferences */ now = time(NULL); - if (argc != 2) - return RESULT_SHOWUSAGE; - conf = confs; - if (!conf) { + cnf = confs; + if (!cnf) { ast_cli(fd, "No active conferences.\n"); return RESULT_SUCCESS; } ast_cli(fd, header_format, "Conf Num", "Parties", "Activity", "Creation"); - while(conf) { - hr = (now - conf->start) / 3600; - min = ((now - conf->start) % 3600) / 60; - sec = (now - conf->start) % 60; + while(cnf) { + hr = (now - cnf->start) / 3600; + min = ((now - cnf->start) % 3600) / 60; + sec = (now - cnf->start) % 60; - if (conf->isdynamic) - ast_cli(fd, data_format, conf->confno, conf->users, hr, min, sec, "Dynamic"); + if (cnf->isdynamic) + ast_cli(fd, data_format, cnf->confno, cnf->users, hr, min, sec, "Dynamic"); else - ast_cli(fd, data_format, conf->confno, conf->users, hr, min, sec, "Static"); + ast_cli(fd, data_format, cnf->confno, cnf->users, hr, min, sec, "Static"); - conf = conf->next; + cnf = cnf->next; } return RESULT_SUCCESS; + } + if (argc < 3) + return RESULT_SHOWUSAGE; + strncpy(cmdline, argv[2], 100); + if (strstr(argv[1], "lock")) { + if (strcmp(argv[1], "lock") == 0) { + /* Lock */ + strcat(cmdline, "|L"); + } else { + /* Unlock */ + strcat(cmdline, "|l"); + } + } else if (strstr(argv[1], "mute")) { + if (argc < 4) + return RESULT_SHOWUSAGE; + if (strcmp(argv[1], "mute") == 0) { + /* Mute */ + strcat(cmdline, "|M|"); + strcat(cmdline, argv[3]); + } else { + /* Unmute */ + strcat(cmdline, "|m|"); + strcat(cmdline, argv[3]); + } + } else if (strcmp(argv[1], "kick") == 0) { + if (argc < 4) + return RESULT_SHOWUSAGE; + if (strcmp(argv[3], "all") == 0) { + /* Kick all */ + strcat(cmdline, "|K"); + } else { + /* Kick a single user */ + strcat(cmdline, "|k|"); + strcat(cmdline, argv[3]); + } + } else if(strcmp(argv[1], "list") == 0) { + /* List all the users in a conference */ + if (!confs) { + ast_cli(fd, "No active conferences.\n"); + return RESULT_SUCCESS; + } + cnf = confs; + /* Find the right conference */ + while(cnf) { + if (strcmp(cnf->confno, argv[2]) == 0) + break; + if (cnf->next) { + cnf = cnf->next; + } else { + ast_cli(fd, "No such conference: %s.\n",argv[2]); + return RESULT_SUCCESS; + } + } + /* Show all the users */ + user = cnf->firstuser; + while(user) { + ast_cli(fd, "User Number: %i on Channel: %s\n", user->user_no, user->chan->name); + user = user->nextuser; + } + return RESULT_SUCCESS; + } else + return RESULT_SHOWUSAGE; + ast_log(LOG_NOTICE, "Cmdline: %s\n", cmdline); + admin_exec(NULL, cmdline); + return 0; } -static char show_confs_usage[] = -"Usage: show conferences\n" -" Provides summary information on conferences with active\n" -" participation.\n"; +static char *complete_confcmd(char *line, char *word, int pos, int state) { + #define CONF_COMMANDS 6 + int which = 0, x = 0; + struct ast_conference *cnf = NULL; + struct ast_conf_user *usr = NULL; + char *confno = NULL; + char usrno[50] = ""; + char cmds[CONF_COMMANDS][20] = {"lock", "unlock", "mute", "unmute", "kick", "list"}; + char *myline; + + if (pos == 1) { + /* Command */ + for (x = 0;x < CONF_COMMANDS; x++) { + if (!strncasecmp(cmds[x], word, strlen(word))) { + if (++which > state) { + return strdup(cmds[x]); + } + } + } + } else if (pos == 2) { + /* Conference Number */ + ast_mutex_lock(&conflock); + cnf = confs; + while(cnf) { + if (!strncasecmp(word, cnf->confno, strlen(word))) { + if (++which > state) + break; + } + cnf = cnf->next; + } + ast_mutex_unlock(&conflock); + return cnf ? strdup(cnf->confno) : NULL; + } else if (pos == 3) { + /* User Number || Conf Command option*/ + if (strstr(line, "mute") || strstr(line, "kick")) { + if ((state == 0) && (strstr(line, "kick")) && !(strncasecmp(word, "all", strlen(word)))) { + return strdup("all"); + } + which++; + ast_mutex_lock(&conflock); + cnf = confs; -static struct ast_cli_entry cli_show_confs = { - { "show", "conferences", NULL }, confs_show, - "Show status of conferences", show_confs_usage, NULL }; + /* TODO: Find the conf number from the cmdline (ignore spaces) <- test this and make it fail-safe! */ + myline = strdupa(line); + if (strsep(&myline, " ") && strsep(&myline, " ") && !confno) { + while((confno = strsep(&myline, " ")) && (strcmp(confno, " ") == 0)) + ; + } + + while(cnf) { + if (strcmp(confno, cnf->confno) == 0) { + break; + } + cnf = cnf->next; + } + if (cnf) { + /* Search for the user */ + usr = cnf->firstuser; + while(usr) { + sprintf(usrno, "%i", usr->user_no); + if (!strncasecmp(word, usrno, strlen(word))) { + if (++which > state) + break; + } + usr = usr->nextuser; + } + } + ast_mutex_unlock(&conflock); + return usr ? strdup(usrno) : NULL; + } + } + return NULL; +} + +static char conf_usage[] = +"Usage: meetme (un)lock|(un)mute|kick|list confno usernumber\n" +" Executes a command for the conference or on a conferee\n"; + +static struct ast_cli_entry cli_conf = { + { "meetme", NULL, NULL }, conf_cmd, + "Execute a command on a conference or conferee", conf_usage, complete_confcmd }; static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int confflags) { struct ast_conference *prev=NULL, *cur; + struct ast_conf_user *user = malloc(sizeof(struct ast_conf_user)); int fd; struct zt_confinfo ztc; struct ast_frame *f; @@ -261,16 +452,62 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c int firstpass = 0; int ret = -1; int x; + int menu_active = 0; struct ast_app *app; char *agifile; char *agifiledefault = "conf-background.agi"; + char meetmesecs[30]; ZT_BUFFERINFO bi; char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; char *buf = __buf + AST_FRIENDLY_OFFSET; + user->user_no = 0; /* User number 0 means starting up user! (dead - not in the list!) */ + + if (conf->locked) { + /* Sorry, but this confernce is locked! */ + if (!ast_streamfile(chan, "conf-locked", chan->language)) + ast_waitstream(chan, ""); + goto outrun; + } + conf->users++; + if (confflags & CONFFLAG_ADMINEXIT) { + if (conf->markedusers == -1) { + conf->markedusers = 1; + } else { + conf->markedusers++; + } + } + + ast_mutex_lock(&conflock); + if (conf->firstuser == NULL) { + /* Fill the first new User struct */ + user->user_no = 1; + user->nextuser = NULL; + user->prevuser = NULL; + conf->firstuser = user; + conf->lastuser = user; + } else { + /* Fill the new user struct */ + user->user_no = conf->lastuser->user_no + 1; + user->prevuser = conf->lastuser; + user->nextuser = NULL; + if (conf->lastuser->nextuser != NULL) { + ast_log(LOG_WARNING, "Error in User Management!\n"); + goto outrun; + } else { + conf->lastuser->nextuser = user; + conf->lastuser = user; + } + } + strncpy(user->usrvalue, "test", sizeof(user->usrvalue)); + user->chan = chan; + user->userflags = confflags; + user->adminflags = 0; + ast_mutex_unlock(&conflock); + if (!(confflags & CONFFLAG_QUIET) && conf->users == 1) { if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) ast_waitstream(chan, ""); @@ -388,7 +625,6 @@ zapretry: "Meetme: %s\r\n", chan->name, chan->uniqueid, conf->confno); - if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) { firstpass = 1; if (!(confflags & CONFFLAG_QUIET)) @@ -422,10 +658,20 @@ zapretry: x = 0; ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); } - } else for(;;) { + } else { + if (!strcasecmp(chan->type,"Zap") && (confflags & CONFFLAG_STARMENU)) { + /* Set CONFMUTE mode on Zap channel to mute DTMF tones when the menu is enabled */ + x = 1; + ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); + } + for(;;) { outfd = -1; ms = -1; c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); + + /* Update the struct with the actual confflags */ + user->userflags = confflags; + /* trying to add moh for single person conf */ if (confflags & CONFFLAG_MOH) { if (conf->users == 1) { @@ -440,7 +686,47 @@ zapretry: } } } - /* end modifications */ + + /* Leave if the last marked user left */ + if ((confflags & CONFFLAG_ADMINEXIT) && (conf->markedusers == 0)) { + ret = 0; + break; + } + + /* Check if the admin changed my modes */ + if (user->adminflags) { + /* Set the new modes */ + if ((user->adminflags & ADMINFLAG_MUTED) && (ztc.confmode & ZT_CONF_TALKER)) { + ztc.confmode ^= ZT_CONF_TALKER; + if (ioctl(fd, ZT_SETCONF, &ztc)) { + ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); + ret = -1; + break; + } + } + if (!(user->adminflags & ADMINFLAG_MUTED) && !(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) { + ztc.confmode |= ZT_CONF_TALKER; + if (ioctl(fd, ZT_SETCONF, &ztc)) { + ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); + ret = -1; + break; + } + } + if (user->adminflags & ADMINFLAG_KICKME) { + //You have been kicked. + if (!ast_streamfile(chan, "conf-kicked", chan->language)) + ast_waitstream(chan, ""); + ret = 0; + break; + } + } else if (!(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) { + ztc.confmode |= ZT_CONF_TALKER; + if (ioctl(fd, ZT_SETCONF, &ztc)) { + ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); + ret = -1; + break; + } + } if (c) { if (c->fds[0] != origfd) { @@ -458,13 +744,105 @@ zapretry: if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) { ret = 0; break; - } else if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) { + } else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) { + if (musiconhold) { + ast_moh_stop(chan); + } if ((confflags & CONFFLAG_ADMIN)) { - /* Do admin stuff here */ + /* Admin menu */ + if (!menu_active) { + menu_active = 1; + /* Record this sound! */ + if (!ast_streamfile(chan, "conf-adminmenu", chan->language)) + ast_waitstream(chan, ""); } else { - /* Do user menu here */ + switch(f->subclass - 48) { + case 1: /* Un/Mute */ + menu_active = 0; + if (ztc.confmode & ZT_CONF_TALKER) { + ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER; + confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER; + } else { + ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; + confflags ^= CONFFLAG_MONITOR | CONFFLAG_TALKER; + } + if (ioctl(fd, ZT_SETCONF, &ztc)) { + ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); + ret = -1; + break; + } + if (ztc.confmode & ZT_CONF_TALKER) { + if (!ast_streamfile(chan, "conf-unmuted", chan->language)) + ast_waitstream(chan, ""); + } else { + if (!ast_streamfile(chan, "conf-muted", chan->language)) + ast_waitstream(chan, ""); + } + break; + case 2: /* Un/Lock the Conference */ + menu_active = 0; + if (conf->locked) { + conf->locked = 0; + if (!ast_streamfile(chan, "conf-unlockednow", chan->language)) + ast_waitstream(chan, ""); + } else { + conf->locked = 1; + if (!ast_streamfile(chan, "conf-lockednow", chan->language)) + ast_waitstream(chan, ""); } + break; + default: + menu_active = 0; + /* Play an error message! */ + if (!ast_streamfile(chan, "conf-errormenu", chan->language)) + ast_waitstream(chan, ""); + break; + } + } + } else { + /* User menu */ + if (!menu_active) { + menu_active = 1; + /* Record this sound! */ + if (!ast_streamfile(chan, "conf-usermenu", chan->language)) + ast_waitstream(chan, ""); + } else { + switch(f->subclass - 48) { + case 1: /* Un/Mute */ + menu_active = 0; + if (ztc.confmode & ZT_CONF_TALKER) { + ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER; + confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER; + } else if (!(user->adminflags & ADMINFLAG_MUTED)) { + ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; + confflags ^= CONFFLAG_MONITOR | CONFFLAG_TALKER; + } + if (ioctl(fd, ZT_SETCONF, &ztc)) { + ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); + ret = -1; + break; + } + if (ztc.confmode & ZT_CONF_TALKER) { + if (!ast_streamfile(chan, "conf-unmuted", chan->language)) + ast_waitstream(chan, ""); + } else { + if (!ast_streamfile(chan, "conf-muted", chan->language)) + ast_waitstream(chan, ""); + } + break; + default: + menu_active = 0; + /* Play an error message! */ + if (!ast_streamfile(chan, "errormenu", chan->language)) + ast_waitstream(chan, ""); + break; + } + } + } + if (musiconhold) { + ast_moh_start(chan, NULL); + } } else if (fd != chan->fds[0]) { if (f->frametype == AST_FRAME_VOICE) { if (f->subclass == AST_FORMAT_ULAW) { @@ -493,7 +871,7 @@ zapretry: ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); } } - + } if (fd != chan->fds[0]) close(fd); else { @@ -510,23 +888,17 @@ zapretry: conf_play(conf, LEAVE); outrun: - - ast_mutex_lock(&conflock); - /* Clean up */ - conf->users--; - - ast_log(LOG_DEBUG, "Removed channel %s from ZAP conf %d\n", chan->name, conf->zapconf); - + if (user->user_no) { /* Only cleanup users who really joined! */ manager_event(EVENT_FLAG_CALL, "MeetmeLeave", "Channel: %s\r\n" "Uniqueid: %s\r\n" "Meetme: %s\r\n", chan->name, chan->uniqueid, conf->confno); - - + ast_mutex_lock(&conflock); + conf->users--; + cur = confs; if (!conf->users) { /* No more users -- close this one out */ - cur = confs; while(cur) { if (cur == conf) { if (prev) @@ -542,7 +914,24 @@ outrun: ast_log(LOG_WARNING, "Conference not found\n"); close(conf->fd); free(conf); + } else { + /* Remove the user struct */ + if (user == cur->firstuser) { + cur->firstuser->nextuser->prevuser = NULL; + cur->firstuser = cur->firstuser->nextuser; + } else if (user == cur->lastuser){ + cur->lastuser->prevuser->nextuser = NULL; + cur->lastuser = cur->lastuser->prevuser; + } else { + user->nextuser->prevuser = user->prevuser; + user->prevuser->nextuser = user->nextuser; + } + /* Return the number of seconds the user was in the conf */ + sprintf(meetmesecs, "%i", (int) (user->jointime - time(NULL))); + pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs); + } } + free(user); ast_mutex_unlock(&conflock); return ret; } @@ -692,7 +1081,7 @@ static int conf_exec(struct ast_channel *chan, void *data) confflags |= CONFFLAG_MONITOR; if (strchr(inflags, 'p')) confflags |= CONFFLAG_POUNDEXIT; - if (strchr(inflags, 's')) + if (strchr(inflags, 'u')) confflags |= CONFFLAG_STARMENU; if (strchr(inflags, 't')) confflags |= CONFFLAG_TALKER; @@ -700,6 +1089,8 @@ static int conf_exec(struct ast_channel *chan, void *data) confflags |= CONFFLAG_QUIET; if (strchr(inflags, 'M')) confflags |= CONFFLAG_MOH; + if (strchr(inflags, 'x')) + confflags |= CONFFLAG_ADMINEXIT; if (strchr(inflags, 'b')) confflags |= CONFFLAG_AGI; if (strchr(inflags, 'd')) @@ -873,10 +1264,102 @@ static int conf_exec(struct ast_channel *chan, void *data) return res; } +static struct ast_conf_user* find_user(struct ast_conference *conf, char *callerident) { + struct ast_conf_user *user = NULL; + char usrno[1024] = ""; + if (conf && callerident) { + user = conf->firstuser; + while(user) { + sprintf(usrno, "%i", user->user_no); + if (strcmp(usrno, callerident) == 0) + return user; + user = user->nextuser; + } + } + return NULL; +} + +static int admin_exec(struct ast_channel *chan, void *data) { + /* MeetMeAdmin(confno, command, caller) */ + char *params, *command = NULL, *caller = NULL, *conf = NULL; + struct ast_conference *cnf; + struct ast_conf_user *user = NULL; + + ast_mutex_lock(&conflock); + /* The param has the conference number the user and the command to execute */ + if (data && strlen(data)) { + params = ast_strdupa((char *) data); + conf = strsep(¶ms, "|"); + command = strsep(¶ms, "|"); + caller = strsep(¶ms, "|"); + + ast_mutex_lock(&conflock); + cnf = confs; + while (cnf) { + if (strcmp(cnf->confno, conf) == 0) + break; + cnf = cnf->next; + } + ast_mutex_unlock(&conflock); + + if (caller) + user = find_user(cnf, caller); + + if (cnf) { + switch((int) (*command)) { + case 76: /* L: Lock */ + cnf->locked = 1; + break; + case 108: /* l: Unlock */ + cnf->locked = 0; + break; + case 75: /* K: kick all users*/ + user = cnf->firstuser; + while(user) { + user->adminflags |= ADMINFLAG_KICKME; + if (user->nextuser) { + user = user->nextuser; + } else { + break; + } + } + break; + case 77: /* M: Mute */ + if (user) { + user->adminflags |= ADMINFLAG_MUTED; + } else { + ast_log(LOG_NOTICE, "Specified User not found!"); + } + break; + case 109: /* m: Unmute */ + if (user && (user->adminflags & ADMINFLAG_MUTED)) { + user->adminflags ^= ADMINFLAG_MUTED; + } else { + ast_log(LOG_NOTICE, "Specified User not found or he muted himself!"); + } + break; + case 107: /* k: Kick user */ + if (user) { + user->adminflags |= ADMINFLAG_KICKME; + } else { + ast_log(LOG_NOTICE, "Specified User not found!"); + } + break; + } + } else { + ast_log(LOG_NOTICE, "Conference Number not found\n"); + } + } + ast_mutex_unlock(&conflock); + return 0; +} + int unload_module(void) { STANDARD_HANGUP_LOCALUSERS; ast_cli_unregister(&cli_show_confs); + ast_cli_unregister(&cli_conf); + ast_unregister_application(app3); ast_unregister_application(app2); return ast_unregister_application(app); } @@ -884,6 +1367,8 @@ int unload_module(void) int load_module(void) { ast_cli_register(&cli_show_confs); + ast_cli_register(&cli_conf); + ast_register_application(app3, admin_exec, synopsis3, descrip3); ast_register_application(app2, count_exec, synopsis2, descrip2); return ast_register_application(app, conf_exec, synopsis, descrip); } diff --git a/channel.c b/channel.c index 896fa89983..cd7aaeba87 100755 --- a/channel.c +++ b/channel.c @@ -468,6 +468,19 @@ struct ast_channel *ast_channel_walk_locked(struct ast_channel *prev) } +struct ast_channel *ast_get_channel_by_name_locked(char *channame) +{ + struct ast_channel *chan; + chan = ast_channel_walk_locked(NULL); + while(chan) { + if (!strcasecmp(chan->name, channame)) + return chan; + ast_mutex_unlock(&chan->lock); + chan = ast_channel_walk_locked(NULL); + } + return NULL; +} + int ast_safe_sleep_conditional( struct ast_channel *chan, int ms, int (*cond)(void*), void *data ) { diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index baae962138..758670f282 100755 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -628,6 +628,9 @@ int ast_recvchar(struct ast_channel *chan, int timeout); */ struct ast_channel *ast_channel_walk_locked(struct ast_channel *prev); +//! Get channel by name (locks channel) +struct ast_channel *ast_get_channel_by_name_locked(char *channame); + //! Waits for a digit /*! * \param c channel to wait for a digit on diff --git a/manager.c b/manager.c index 53dcf6f094..b619baf044 100755 --- a/manager.c +++ b/manager.c @@ -455,6 +455,7 @@ static int action_redirect(struct mansession *s, struct message *m) char *exten = astman_get_header(m, "Exten"); char *context = astman_get_header(m, "Context"); char *priority = astman_get_header(m, "Priority"); + struct ast_channel *chan, *chan2 = NULL; int pi = 0; int res; if (!name || !strlen(name)) { @@ -465,10 +466,16 @@ static int action_redirect(struct mansession *s, struct message *m) astman_send_error(s, m, "Invalid priority\n"); return 0; } - res = ast_async_goto_by_name(name, context, exten, pi); + chan = ast_get_channel_by_name_locked(name); + if (strlen(name2)) + chan2 = ast_get_channel_by_name_locked(name2); + res = ast_async_goto(chan, context, exten, pi); if (!res) { if (strlen(name2)) { - res = ast_async_goto_by_name(name2, context, exten, pi); + if (chan2) + res = ast_async_goto(chan2, context, exten, pi); + else + res = -1; if (!res) astman_send_ack(s, m, "Dual Redirect successful"); else @@ -477,6 +484,10 @@ static int action_redirect(struct mansession *s, struct message *m) astman_send_ack(s, m, "Redirect successful"); } else astman_send_error(s, m, "Redirect failed"); + if (chan) + ast_mutex_unlock(&chan->lock); + if (chan2) + ast_mutex_unlock(&chan2->lock); return 0; } diff --git a/sounds.txt b/sounds.txt index 419497c71a..ce7e5a4a87 100755 --- a/sounds.txt +++ b/sounds.txt @@ -612,3 +612,21 @@ %plus.gsm%plus [+] %equals.gsm%equals [=] + +%conf-locked.gsm%This conference is locked! + +%conf-kicked.gsm%You have been kicked from this conference + +%conf-adminmenu.gsm%Please press 1 to mute or unmute yourself, or press 2 to lock or unlock the conference + +%conf-usermenu.gsm%Please press 1 to mute or unmute yourself + +%conf-errormenu.gsm%Invalid Choice + +%conf-muted.gsm%You are now muted + +%conf-unmuted.gsm%You are now unmuted + +%conf-lockednow.gsm%The conference is now locked + +%conf-unlockednow.gsm%The conference is now unlocked diff --git a/sounds/conf-adminmenu.gsm b/sounds/conf-adminmenu.gsm new file mode 100755 index 0000000000000000000000000000000000000000..ba5301717ecca001edee8ce1a29364af036ddb09 GIT binary patch literal 11187 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 JV>>Pj`M(M)Oyd9m literal 0 HcmV?d00001 diff --git a/sounds/conf-errormenu.gsm b/sounds/conf-errormenu.gsm new file mode 100755 index 0000000000000000000000000000000000000000..6388c1c5201dd4ae69ab43b2c5ea594f8818fe48 GIT binary patch literal 2376 zcmV-O3AgsvT2a)QP(UW!ZMNH5AV(vS$mFU3NaS)j+iJiyB#p-8*PUtD(wrbR+ik?$ z#$ZU}jmYa(pgALMMu6;om2TMB9ZIW}E#nD1u6Ex{mO;i@wbt4+ zcSMx0HidE7wBD^GHEKVimntEuaeUI?%#R#%=F!!hEjCl(4GN`pR@&idsa=gCFW(D^ z9FeBw-zQBiXcgVko^3tb-AP9+dj?+MhKn0{(JJC({aXb|g5*VO7zx_X(Jb8MqUM9k zQB_tS-lAHQinH$Af>za4we;MgK^)Bc+R-oDS@6)N`jUqU@RyL#4 z0T0upHIR&gdR(=_#oFPn>k${L(q4^e^uNa2#u0~lbjM9%LY-2YrETOUA4HvE?xASr zvCy&)U{)mcJ@f*@$lOgl0q*-+iqT{fnYV3lv zq3GpTB%C;mz=PB4QDW899CKY{yo4ncvX33qgD6tV==EO0oFpbmYs7;7qD&WU)ZKjQ zT5;&fBn_IRWa-OmY#42w&bcgzj^t9ZyCX>WeENZo06~C+8Q||-mXTF z@mXEpEVoCg^t9CHy&VgeuF5K|rzPXiz@BxvB$-j6WRg1Tn+~znu1e|DZN#Mu=S_|_ zb;(SdES7e4y8`EMH)M`RkC&{ptE#(&)at|_%au-9B#x*l-%DJxjZxQ?YdYe9b>ovu z#~UM^Bh;$9oePmlteYKMEY~Y!+3Pu!jp&|psmNf_Obn)0Hb>NKx}6J&%%#+ATJeUg zc{491>#Ysz7p9XuyNiHQtM%RM~nCU{>ZNp1Z26H@P5#K?wWJ88m#TPgWmaycSjh}GP6 z#^hrsqQ&LoD$^a@R#U@BT9YYqxn*a!YiYA^$3@9IS67Z_M!D;bNix%!y_(Bs#TsD2 zIbvx=OIvKdWYHua8M4&F&qsLMnkj42-OZ|sYos{p7Drjr#km}AL1bxU>Z7@o57P$= zQ?f-Y(k9)m2+>8NWbrj#+9S6}YAamgA#P*Q;+gIt$d$Lrq|mMOUCH2}%qt1EYtTT) zWJ)r=;9#2_ZMfOqAgHd6StHP_+v%F#pvfvpxudke*(8=SQ?9_vo0dl_=HQguauL&^@U*4h*h#1m`E=D7%~3S32UF4@Dj<;{QBt;y}K!>{o z`^Ij@%3Y+2o2|to)30!E8DD|$sd|>jU!^%+J-FMyMY|L!btGZJOgwMcbJJ{jCm6va z+-y3hL1UvXv5iw@$0nvOmMY`PbJql0ZOJZ9#@aG7E3n$=oGD+=hNT_fHk$?F5X&Ti=BcVjf$61fj~LE$pJ zHp+h)4ad10BOV=b#%!L?Kh4At2pXca29p`UMhQVN2ir4*g1B+8;` zEe0BCdqNk}iDNO^rMp@6kVzcW!iFV^IV66f%Og?BBc_4J4pTd}qFY*N;GmYmMx%+vgxY4x=+N+?rwK5@BjTadbtWeP$f1Q1P`BIS zfvWIs%Rbttv*^&YqN$&2tmJfor~+ZcV#0wI#St~0Q6bOvo6g;=*?z9vqIE5nSmKI+>UuUo zOxhx%oQU3mDI^W7oamuc@}g$+cA+?9E(WC1p%o)Brd`+`k|3e*p&3KctsK0eJtcKg z{;r}l9G1x&THu=WYRlr+r-0cY)BxJMea{SL;Kp8wmf^$zw&886<+1=Lq?dp5)zxYg z;q2f^T$#9((qJ^>aWxy(Ku05zHxt}IM=O!LB-5B#onfSaM;w+nBXFQbwbVp+-^GKlz=$gjmYF6jn9q% literal 0 HcmV?d00001 diff --git a/sounds/conf-kicked.gsm b/sounds/conf-kicked.gsm new file mode 100755 index 0000000000000000000000000000000000000000..33ef20cd66244d50bc0744648eb3174154e81575 GIT binary patch literal 3861 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 literal 0 HcmV?d00001 diff --git a/sounds/conf-locked.gsm b/sounds/conf-locked.gsm new file mode 100755 index 0000000000000000000000000000000000000000..82b59be5d2805374724ceb741e0cb6e58af2a147 GIT binary patch literal 2805 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 literal 0 HcmV?d00001 diff --git a/sounds/conf-lockednow.gsm b/sounds/conf-lockednow.gsm new file mode 100755 index 0000000000000000000000000000000000000000..0288ff62b3edf048ca6abdbb60eccbb16cb6bcc0 GIT binary patch literal 3597 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 literal 0 HcmV?d00001 diff --git a/sounds/conf-muted.gsm b/sounds/conf-muted.gsm new file mode 100755 index 0000000000000000000000000000000000000000..014a58998b3d69cec7a468c26031083c6a64275a GIT binary patch literal 2178 zcmV-|2z~e0oO#%hPyksZl1XG+z&7JfHq=lcHrsAU+mL`qBa%5I*WZ#HnN~nYBa%53 z-~cw`jyD^^AUNA?w&m_1NaT`99Mu|=DB5ViM&xcb+_fM^+>N&!kbpMhjmF!|z(*sF zId#+0v^`bRqBh93%XL-ew#Tu#Bw1p@1RE&#TjAOP#B$PQm=)4+pktzU1)rq&oY>=#ZjY)XB zhgn-YDHs5w>)bfb^z$rN}y zU604ZW*MuqjSe=2l1XIMq(r7_jfn_2(YYs&j&z%GwI$UI1!U0{;f-n6x-cJR)gDx{ z8r5lS2t4Xuj|f=CxkfaOsVSQgw&(6=;!#CU|IuvBX(R5+MG6heB;Z1`1%ls^(jusB z3w;RQ0@pD=WJJ+y%c-lALO9QrwOibyMt!Xqq>&++ZDmJb*&*Fx5n7JYBFyqqkD)l& zi#xj2g5;AOOAEWvx8c?zoUMX+ZAb<>-q^9w zisOyN9j}U;>Efqq=TJ5(vbK!XCes~@<*p|CZMNNWZPw3{)gp0;`ys+pi{a_PKF$`} z)a=4tRBimxTlX+kV^$DY>A5uCNk+m%R*E6%L!)NPnCk>bn@rLMZ_>Wd-G)=6YlXn~fM z$zxf_HoSGkRn#>vjyB+iqwf4|(+Fc>v#gPByv0Jc zXxV7A(dnwG>tOMT~l1A_(--KqFrwNe4^tAyV?Pd0+l>%MuCD|60fe+PIO}+@7 z=33)%t|C*aw`ypvwVR__=}W0zne6Df?&#%X!7O<> z0+~fjt5R1GECo36q<_mWD}RKT}! zX;p)up}3+liydZxQDbszA=##p<0apl?x{*s`R|l>mi$$!nCj(64M*dqS)SG9E6w@4ixqUneOR?bvX?CoZCr#`M#keYV2Gs1~G-T7=0cJy=53Wot(?rj4X| ze8u?ohHntm9%Xj|)W;!fmD=6f$JrV|^&@pe=vJ~8m~O@P^mfH7)m=t876tdC!nIrjn!IQuR(OgQ!VMDfO#Z$Q zs+iQ9WV1tiBChmOXzYN(*%To9<9OoVW1Y5IfZ>Inj#%B&+H7|idcipxafKT0Am+t$ zIOmo?L~3+sjJzOeYx4&q)LL_K*}}jnGLmU6f`B&EjV7X=phX*w*K(9VJnU)dS<;`I zk>XgOIV5qk?SSAW<4#E3)nQW-k;yGuKwMBJNb}cQs-z>%pzB*nWai|7x$B|Jvt#2V z$S*r(SIF7RYC7iGW_h*HYNZC(B=*{3LjMv(V&|tGOj=hqs z;L6hxnHtvIVQC7`AU2a3>Rf~XWYw0pW57T+oR&u=pdd)%ZM56gSb|*Hn4m`+ZN(g_ zKsh9mNh07NIOB1-98@4D8(1k5T*b(9gWFkbU-HCZN}WFph+9fNgPxFNhFd< EBpa1v+5i9m literal 0 HcmV?d00001 diff --git a/sounds/conf-unlockednow.gsm b/sounds/conf-unlockednow.gsm new file mode 100755 index 0000000000000000000000000000000000000000..a9cfe0077c107a61f1705cc45c811c7366ae6c6d GIT binary patch literal 4290 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