Started unification of CLI and AMI code. Fixed numerous bugs in AMI and CLI commands. Add AMI CapichatMute, CapichatUnmute and CapiCommand commands

This commit is contained in:
MelwareDE 2010-11-04 19:17:16 +00:00
parent 9c3cceccda
commit 487fb33bb9
6 changed files with 318 additions and 107 deletions

View File

@ -131,7 +131,7 @@ SHAREDOS=chan_capi.so
OBJECTS=chan_capi.o chan_capi_utils.o chan_capi_rtp.o chan_capi_command.o xlaw.o dlist.o \
chan_capi_qsig_core.o chan_capi_qsig_ecma.o chan_capi_qsig_asn197ade.o \
chan_capi_qsig_asn197no.o chan_capi_supplementary.o chan_capi_chat.o \
chan_capi_mwi.o chan_capi_cli.o chan_capi_ami.o
chan_capi_mwi.o chan_capi_cli.o chan_capi_ami.o chan_capi_management_common.o
ifeq (${USE_OWN_LIBCAPI},yes)
OBJECTS += libcapi20/convert.o libcapi20/capi20.o libcapi20/capifunc.o

View File

@ -25,23 +25,34 @@
* Based on apps/app_meetme.c
*
*/
#ifdef CC_AST_HAS_VERSION_1_6
#include "chan_capi_platform.h"
#include "chan_capi20.h"
#include "chan_capi.h"
#ifdef CC_AST_HAS_VERSION_1_6
#include "chan_capi_qsig.h"
#include "chan_capi_utils.h"
#include "chan_capi_chat.h"
#include "chan_capi_management_common.h"
#include "asterisk/manager.h"
#define CC_AMI_ACTION_NAME_CHATLIST "CapichatList"
#define CC_AMI_ACTION_NAME_CHATLIST "CapichatList"
#define CC_AMI_ACTION_NAME_CHATMUTE "CapichatMute"
#define CC_AMI_ACTION_NAME_CHATUNMUTE "CapichatUnmute"
#define CC_AMI_ACTION_NAME_CAPICOMMAND "CapiCommand"
/*
LOCALS
*/
static int pbx_capi_ami_capichat_list(struct mansession *s, const struct message *m);
static int pbx_capi_ami_capichat_mute(struct mansession *s, const struct message *m);
static int pbx_capi_ami_capichat_unmute(struct mansession *s, const struct message *m);
static int pbx_capi_ami_capichat_control(struct mansession *s, const struct message *m, int chatMute);
static int pbx_capi_ami_capicommand(struct mansession *s, const struct message *m);
static int capiChatListRegistered;
static int capiChatMuteRegistered;
static int capiChatUnmuteRegistered;
static int capiCommandRegistered;
static char mandescr_capichatlist[] =
"Description: Lists all users in a particular CapiChat conference.\n"
@ -51,6 +62,28 @@ static char mandescr_capichatlist[] =
" *ActionId: <id>\n"
" *Conference: <confname>\n";
static char mandescr_capichatmute[] =
"Description: Mutes user in a particular CapiChat conference.\n"
"Variables:\n"
" *ActionId: <id>\n"
" *Conference: <confname>\n"
" *Member: <membername>\n"
" *Path: <Rx or Tx>\n";
static char mandescr_capichatunmute[] =
"Description: Unmutes user in a particular CapiChat conference.\n"
"Variables:\n"
" *ActionId: <id>\n"
" *Conference: <confname>\n"
" *Member: <membername>\n"
" *Path: <Rx or Tx>\n";
static char mandescr_capicommand[] =
"Description: Exec capicommand.\n"
"Variables:\n"
" *ActionId: <id>\n"
" *Channel: <channame>\n"
" *Capicommand: <capicommand>\n";
void pbx_capi_ami_register(void)
{
@ -59,12 +92,39 @@ void pbx_capi_ami_register(void)
pbx_capi_ami_capichat_list,
"List participants in a conference",
mandescr_capichatlist) == 0;
capiChatMuteRegistered = ast_manager_register2(CC_AMI_ACTION_NAME_CHATMUTE,
EVENT_FLAG_CALL,
pbx_capi_ami_capichat_mute,
"Mute a conference user",
mandescr_capichatmute) == 0;
capiChatUnmuteRegistered = ast_manager_register2(CC_AMI_ACTION_NAME_CHATUNMUTE,
EVENT_FLAG_CALL,
pbx_capi_ami_capichat_unmute,
"Unmute a conference user",
mandescr_capichatunmute) == 0;
capiCommandRegistered = ast_manager_register2(CC_AMI_ACTION_NAME_CAPICOMMAND,
EVENT_FLAG_CALL,
pbx_capi_ami_capicommand,
"Exec capicommand",
mandescr_capicommand) == 0;
}
void pbx_capi_ami_unregister(void)
{
if (capiChatListRegistered != 0)
ast_manager_unregister(CC_AMI_ACTION_NAME_CHATLIST);
if (capiChatMuteRegistered != 0)
ast_manager_unregister(CC_AMI_ACTION_NAME_CHATMUTE);
if (capiChatUnmuteRegistered != 0)
ast_manager_unregister(CC_AMI_ACTION_NAME_CHATUNMUTE);
if (capiCommandRegistered != 0)
ast_manager_unregister(CC_AMI_ACTION_NAME_CAPICOMMAND);
}
static int pbx_capi_ami_capichat_list(struct mansession *s, const struct message *m) {
@ -165,6 +225,98 @@ static int pbx_capi_ami_capichat_list(struct mansession *s, const struct message
"\r\n", total, idText);
return 0;
}
static int pbx_capi_ami_capichat_mute(struct mansession *s, const struct message *m)
{
return pbx_capi_ami_capichat_control(s, m, 1);
}
static int pbx_capi_ami_capichat_unmute(struct mansession *s, const struct message *m)
{
return pbx_capi_ami_capichat_control(s, m, 0);
}
static int pbx_capi_ami_capichat_control(struct mansession *s, const struct message *m, int chatMute)
{
const char *roomName = astman_get_header(m, "Conference");
const char *userName = astman_get_header(m, "Member");
const char *voicePath = astman_get_header(m, "Path");
const char* capiCommand;
int ret;
if (ast_strlen_zero(roomName)) {
astman_send_error(s, m, "Capi Chat conference not specified");
return 0;
}
if (ast_strlen_zero(userName)) {
char* param = ast_strdupa((chatMute != 0) ? "yes" : "no");
int ret = pbx_capi_chat_mute(NULL, param);
if (ret == 0) {
astman_send_ack(s, m, (chatMute != 0) ? "Conference muted" : "Conference unmuted");
} else {
astman_send_error(s, m, "Failed to change mode of Capi Chat conference");
}
return 0;
}
if ((voicePath != NULL) && (strcmp(voicePath, "Rx") == 0)) {
capiCommand = (chatMute != 0) ? "rxdgain,-128" : "rxdgain,0";
} else {
capiCommand = (chatMute != 0) ? "txdgain,-128" : "txdgain,0";
}
ret = pbx_capi_management_capicommand(userName, capiCommand);
switch (ret) {
case 0:
astman_send_ack(s, m, (chatMute != 0) ? "User muted" : "User unmuted");
break;
case -4:
astman_send_error(s, m, "User not found");
break;
default:
astman_send_error(s, m, "Command error");
break;
}
return (0);
}
static int pbx_capi_ami_capicommand(struct mansession *s, const struct message *m)
{
const char *requiredChannelName = astman_get_header(m, "Channel");
const char *chancapiCommand = astman_get_header(m, "Command");
int ret = pbx_capi_management_capicommand(requiredChannelName, chancapiCommand);
switch (ret) {
case 0:
astman_send_ack(s, m, "OK");
break;
case -2:
astman_send_error(s, m, "Channel name not specified");
break;
case -3:
astman_send_error(s, m, "Capi command name not specified");
break;
case -4:
astman_send_error(s, m, "Channel not found");
break;
case -1:
default:
astman_send_error(s, m, "Command error");
break;
}
return 0;
}
#else
void pbx_capi_ami_register(void)
{

View File

@ -916,13 +916,16 @@ int pbx_capi_chat_command(struct ast_channel *c, char *param)
struct capi_pvt* pbx_check_resource_plci(struct ast_channel *c)
{
struct capi_pvt *i = NULL;
const char* id = pbx_builtin_getvar_helper(c, "RESOURCEPLCI");
if (id != 0) {
i = (struct capi_pvt*)strtoul(id, NULL, 0);
if (i != 0 && capi_verify_resource_plci(i) != 0) {
cc_log(LOG_ERROR, "resource PLCI lost\n");
i = 0;
if (c != NULL) {
const char* id = pbx_builtin_getvar_helper(c, "RESOURCEPLCI");
if (id != 0) {
i = (struct capi_pvt*)strtoul(id, NULL, 0);
if (i != 0 && capi_verify_resource_plci(i) != 0) {
cc_log(LOG_ERROR, "resource PLCI lost\n");
i = 0;
}
}
}

View File

@ -21,15 +21,11 @@
#include "chan_capi_utils.h"
#include "chan_capi_chat.h"
#include "chan_capi_cli.h"
#include "chan_capi_management_common.h"
#ifdef DIVA_STATUS
#include "divastatus_ifc.h"
#endif
/*
LOCALS
*/
static int pbx_capi_cli_get_locks(struct capi_pvt *i);
/*
* usages
*/
@ -542,25 +538,11 @@ static char *pbxcli_capi_exec_capicommand(struct ast_cli_entry *e, int cmd, stru
static int pbxcli_capi_exec_capicommand(int fd, int argc, char *argv[])
#endif
{
int ifc_type, found, retry_search, search_loops = 10;
struct capi_pvt *i;
int required_args = 4;
int provided_args;
const char* requiredChannelName = NULL;
const char* chancapiCommand = NULL;
int ret = -1;
struct {
struct capi_pvt *head;
void (*lock_proc)(void);
void (*unlock_proc)(void);
} data[2];
data[0].head = capi_iflist;
data[0].lock_proc = pbx_capi_lock_interfaces;
data[0].unlock_proc = pbx_capi_unlock_interfaces;
data[1].head = (struct capi_pvt*)pbx_capi_get_nulliflist();
data[1].lock_proc = pbx_capi_nulliflist_lock;
data[1].unlock_proc = pbx_capi_nulliflist_unlock;
int ret;
#ifdef CC_AST_HAS_VERSION_1_6
if (cmd == CLI_INIT) {
@ -585,57 +567,7 @@ static int pbxcli_capi_exec_capicommand(int fd, int argc, char *argv[])
chancapiCommand = argv[3];
#endif
do {
retry_search = 0;
for (ifc_type = 0, found = 0; (found == 0) && (ifc_type < sizeof(data)/sizeof(data[0])); ifc_type++) {
data[ifc_type].lock_proc();
for (i = data[ifc_type].head; (i != 0); i = i->next) {
char* name;
if ((i->used == 0) || ((i->channeltype != CAPI_CHANNELTYPE_B) &&
(i->channeltype != CAPI_CHANNELTYPE_NULL)))
continue;
if (i->data_plci != 0)
continue;
name = ast_strdup(i->vname);
if ((i->channeltype == CAPI_CHANNELTYPE_NULL) && (name != NULL)) {
char* p = strstr(name, "-DATAPLCI");
if (p != NULL)
*p = 0;
}
if (strcmp(requiredChannelName, (name == 0) ? i->vname : name) == 0) {
found = 1;
ast_free(name);
retry_search = pbx_capi_cli_get_locks(i);
break;
}
ast_free(name);
}
data[ifc_type].unlock_proc();
}
if (retry_search != 0) {
usleep (100);
i = 0;
}
} while ((retry_search != 0) && (search_loops-- > 0));
if (i != NULL) {
if (i->channeltype != CAPI_CHANNELTYPE_NULL) {
struct ast_channel* c = i->owner;
ret = pbx_capi_cli_exec_capicommand(c, chancapiCommand);
cc_mutex_unlock(&i->lock);
if (c)
ast_channel_unlock (c);
} else {
ret = pbx_capi_cli_exec_capicommand(i->used, chancapiCommand);
cc_mutex_unlock(&i->lock);
}
}
ret = pbx_capi_management_capicommand(requiredChannelName, chancapiCommand);
#ifdef CC_AST_HAS_VERSION_1_6
return ((ret == 0) ? CLI_SUCCESS : CLI_FAILURE);
@ -796,30 +728,3 @@ void pbx_capi_cli_unregister(void)
#endif
}
static int pbx_capi_cli_get_locks(struct capi_pvt *i)
{
if (i->channeltype != CAPI_CHANNELTYPE_NULL) {
struct ast_channel* c = i->owner;
if (c != 0) {
if (ast_channel_trylock(c) == 0) {
if (ast_mutex_trylock(&i->lock) == 0) {
if (i->owner == c) {
return (0);
} else {
ast_mutex_unlock(&i->lock);
ast_channel_unlock (c);
}
} else {
ast_channel_unlock (c);
}
}
}
} else {
if (ast_mutex_trylock(&i->lock) == 0) {
return (0);
}
}
return (-1);
}

View File

@ -0,0 +1,144 @@
/*
*
Copyright (c) Dialogic (R) 2009 - 2010
*
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters.
*
Dialogic (R) File Revision : 1.9
*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
*
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* Based on apps/app_meetme.c
*
*/
#include "chan_capi_platform.h"
#include "chan_capi20.h"
#include "chan_capi.h"
#include "chan_capi_qsig.h"
#include "chan_capi_utils.h"
#include "chan_capi_chat.h"
/*
LOCALS
*/
static int pbx_capi_get_all_locks (struct capi_pvt *i, struct ast_channel** usedChannel);
/*!
\brief Execute any capicommand
\note Called from CLI or from AMI context
*/
int pbx_capi_management_capicommand(const char *requiredChannelName, const char *chancapiCommand) {
int ifc_type, retry_search, search_loops;
struct capi_pvt *i;
struct {
struct capi_pvt *head;
void (*lock_proc)(void);
void (*unlock_proc)(void);
} data[2];
data[0].head = capi_iflist;
data[0].lock_proc = pbx_capi_lock_interfaces;
data[0].unlock_proc = pbx_capi_unlock_interfaces;
data[1].head = (struct capi_pvt*)pbx_capi_get_nulliflist();
data[1].lock_proc = pbx_capi_nulliflist_lock;
data[1].unlock_proc = pbx_capi_nulliflist_unlock;
if (ast_strlen_zero(requiredChannelName)) {
return -2;
}
if (ast_strlen_zero(chancapiCommand)) {
return -3;
}
for (ifc_type = 0; ifc_type < sizeof(data)/sizeof(data[0]); ifc_type++) {
search_loops = 10;
do {
data[ifc_type].lock_proc();
for (i = data[ifc_type].head, retry_search = 0; i != 0; i = i->next) {
struct ast_channel* c = NULL;
if ((i->used == 0) || ((i->channeltype != CAPI_CHANNELTYPE_B) &&
(i->channeltype != CAPI_CHANNELTYPE_NULL)))
continue;
if (i->data_plci != 0)
continue;
if (pbx_capi_get_all_locks (i, &c) != 0) {
retry_search = 1;
break;
}
if ((!ast_strlen_zero(c->name) && (strcmp(requiredChannelName, c->name) == 0)) ||
strcmp(requiredChannelName, i->vname) == 0) {
struct ast_channel* usedChannel = c;
int ret;
data[ifc_type].unlock_proc();
if (i->channeltype != CAPI_CHANNELTYPE_NULL) {
ret = (pbx_capi_cli_exec_capicommand(usedChannel, chancapiCommand) == 0) ? 0 : -1;
cc_mutex_unlock(&i->lock);
ast_channel_unlock(c);
} else {
ast_channel_unlock(c);
ret = (pbx_capi_cli_exec_capicommand(usedChannel, chancapiCommand) == 0) ? 0 : -1;
cc_mutex_unlock(&i->lock);
}
return ret;
}
cc_mutex_unlock(&i->lock);
ast_channel_unlock(c);
}
data[ifc_type].unlock_proc();
if (retry_search != 0) {
usleep (100);
}
} while((retry_search != 0) && (search_loops-- > 0));
}
return -4;
}
/*!
* \brief Try to take all locks. Called with false lock order
* one of the list locks (iflock or nullif_lock) taken
* Used by CLI/AMI
*/
static int pbx_capi_get_all_locks (struct capi_pvt *i, struct ast_channel** usedChannel)
{
struct ast_channel* c = (i->channeltype != CAPI_CHANNELTYPE_NULL) ? i->owner : i->used;
if (c != 0) {
if (ast_channel_trylock(c) == 0) {
if (ast_mutex_trylock(&i->lock) == 0) {
struct ast_channel* cref = (i->channeltype != CAPI_CHANNELTYPE_NULL) ? i->owner : i->used;
if (cref == c) {
*usedChannel = c;
return (0);
} else {
ast_mutex_unlock(&i->lock);
ast_channel_unlock (c);
}
} else {
ast_channel_unlock (c);
}
}
}
return (-1);
}

View File

@ -0,0 +1,7 @@
#ifndef __CC_MANAGEMENT_COMMON_INTERFACE_H__
#define __CC_MANAGEMENT_COMMON_INTERFACE_H__
int pbx_capi_management_capicommand(const char *requiredChannelName, const char *chancapiCommand);
#endif