Add chat_connect to interconnect two chat roouss using NULL PLCI

This commit is contained in:
MelwareDE 2010-11-24 17:08:11 +00:00
parent 29581c9637
commit a60f4cf67a
8 changed files with 212 additions and 66 deletions

View File

@ -7230,59 +7230,61 @@ static struct capicommands_s {
pbx_capi_command_proc_t cmd;
int capionly;
int resourceplcisupported;
int notchannelrelated;
} capicommands[] = {
{ "getid", pbx_capi_get_id, 0, 0 },
{ "peerlink", pbx_capi_peer_link, 0, 0 },
{ "progress", pbx_capi_signal_progress, 1, 0 },
{ "deflect", pbx_capi_call_deflect, 1, 0 },
{ "receivefax", pbx_capi_receive_fax, 1, 1 },
{ "sendfax", pbx_capi_send_fax, 1, 1 },
{ "echosquelch", pbx_capi_echosquelch, 1, 0 },
{ "echocancel", pbx_capi_echocancel, 1, 1 },
{ "getid", pbx_capi_get_id, 0, 0, 0 },
{ "peerlink", pbx_capi_peer_link, 0, 0, 0 },
{ "progress", pbx_capi_signal_progress, 1, 0, 0 },
{ "deflect", pbx_capi_call_deflect, 1, 0, 0 },
{ "receivefax", pbx_capi_receive_fax, 1, 1, 0 },
{ "sendfax", pbx_capi_send_fax, 1, 1, 0 },
{ "echosquelch", pbx_capi_echosquelch, 1, 0, 0 },
{ "echocancel", pbx_capi_echocancel, 1, 1, 0 },
{ "noisesuppressor", pbx_capi_noisesuppressor, 1, 1 },
{ "rxagc", pbx_capi_rxagc, 1, 1 },
{ "txagc", pbx_capi_txagc, 1, 1 },
{ "rxdgain", pbx_capi_rxdgain, 1, 1 },
{ "incrxdgain", pbx_capi_incrxdgain, 1, 1 },
{ "txdgain", pbx_capi_txdgain, 1, 1 },
{ "inctxdgain", pbx_capi_inctxdgain, 1, 1 },
{ "clamping", pbx_capi_clamping, 1, 1 },
{ "mftonedetection", pbx_capi_mftonedetection, 1, 1 },
{ "pulsedetection", pbx_capi_pulsedetection, 1, 1 },
{ "sendtone", pbx_capi_sendtone, 1, 1 },
{ "stoptone", pbx_capi_stoptone, 1, 1 },
{ "starttonedetection", pbx_capi_starttonedetection, 1, 1 },
{ "stoptonedetection", pbx_capi_stoptonedetection, 1, 1 },
{ "pitchcontrol", pbx_capi_pitchcontrol, 1, 1 },
{ "incpitchcontrol", pbx_capi_incpitchcontrol, 1, 1 },
{ "noisesuppressor", pbx_capi_noisesuppressor, 1, 1, 0 },
{ "rxagc", pbx_capi_rxagc, 1, 1, 0 },
{ "txagc", pbx_capi_txagc, 1, 1, 0 },
{ "rxdgain", pbx_capi_rxdgain, 1, 1, 0 },
{ "incrxdgain", pbx_capi_incrxdgain, 1, 1, 0 },
{ "txdgain", pbx_capi_txdgain, 1, 1, 0 },
{ "inctxdgain", pbx_capi_inctxdgain, 1, 1, 0 },
{ "clamping", pbx_capi_clamping, 1, 1, 0 },
{ "mftonedetection", pbx_capi_mftonedetection, 1, 1, 0 },
{ "pulsedetection", pbx_capi_pulsedetection, 1, 1, 0 },
{ "sendtone", pbx_capi_sendtone, 1, 1, 0 },
{ "stoptone", pbx_capi_stoptone, 1, 1, 0 },
{ "starttonedetection", pbx_capi_starttonedetection, 1, 1, 0 },
{ "stoptonedetection", pbx_capi_stoptonedetection, 1, 1, 0 },
{ "pitchcontrol", pbx_capi_pitchcontrol, 1, 1, 0 },
{ "incpitchcontrol", pbx_capi_incpitchcontrol, 1, 1, 0 },
{ "vc", pbx_capi_voicecommand, 1, 1 },
{ "vctransparency", pbx_capi_voicecommand_transparency, 1, 1 },
{ "vc", pbx_capi_voicecommand, 1, 1, 0 },
{ "vctransparency", pbx_capi_voicecommand_transparency, 1, 1, 0 },
{ "getplci", pbx_capi_getplci, 1, 0 },
{ "getplci", pbx_capi_getplci, 1, 0, 0 },
{ "malicious", pbx_capi_malicious, 1, 0 },
{ "keypad", pbx_capi_keypad, 1, 0 },
{ "hold", pbx_capi_hold, 1, 0 },
{ "holdtype", pbx_capi_holdtype, 1, 0 },
{ "retrieve", pbx_capi_retrieve, 0, 0 },
{ "ect", pbx_capi_ect, 1, 0 },
{ "3pty_begin", pbx_capi_3pty_begin, 1, 0 },
{ "ccbs", pbx_capi_ccbs, 0, 0 },
{ "ccbsstop", pbx_capi_ccbsstop, 0, 0 },
{ "ccpartybusy", pbx_capi_ccpartybusy, 0, 0 },
{ "chat", pbx_capi_chat, 0, 0 },
{ "chat_command", pbx_capi_chat_command, 0, 0 },
{ "chat_mute", pbx_capi_chat_mute, 0, 0 },
{ "chat_play", pbx_capi_chat_play, 0, 0 },
{ "resource", pbx_capi_chat_associate_resource_plci, 0, 0 },
{ "mwi", pbx_capi_mwi, 1, 0 },
{ "hangup", pbx_capi_realhangup, 0, 0 },
{ "qsig_ssct", pbx_capi_qsig_ssct, 1, 0 },
{ "qsig_ct", pbx_capi_qsig_ct, 1, 0 },
{ "qsig_callmark",pbx_capi_qsig_callmark, 1, 0 },
{ "qsig_getplci", pbx_capi_qsig_getplci, 1, 0 },
{ "malicious", pbx_capi_malicious, 1, 0, 0 },
{ "keypad", pbx_capi_keypad, 1, 0, 0 },
{ "hold", pbx_capi_hold, 1, 0, 0 },
{ "holdtype", pbx_capi_holdtype, 1, 0, 0 },
{ "retrieve", pbx_capi_retrieve, 0, 0, 0 },
{ "ect", pbx_capi_ect, 1, 0, 0 },
{ "3pty_begin", pbx_capi_3pty_begin, 1, 0, 0 },
{ "ccbs", pbx_capi_ccbs, 0, 0, 0 },
{ "ccbsstop", pbx_capi_ccbsstop, 0, 0, 0 },
{ "ccpartybusy", pbx_capi_ccpartybusy, 0, 0, 0 },
{ "chat", pbx_capi_chat, 0, 0, 0 },
{ "chat_command", pbx_capi_chat_command, 0, 0, 0 },
{ "chat_mute", pbx_capi_chat_mute, 0, 0, 0 },
{ "chat_play", pbx_capi_chat_play, 0, 0, 0 },
{ "chat_connect", pbx_capi_chat_connect, 0, 0, 1 },
{ "resource", pbx_capi_chat_associate_resource_plci, 0, 0, 0 },
{ "mwi", pbx_capi_mwi, 1, 0, 0 },
{ "hangup", pbx_capi_realhangup, 0, 0, 0 },
{ "qsig_ssct", pbx_capi_qsig_ssct, 1, 0, 0 },
{ "qsig_ct", pbx_capi_qsig_ct, 1, 0, 0 },
{ "qsig_callmark",pbx_capi_qsig_callmark, 1, 0, 0 },
{ "qsig_getplci", pbx_capi_qsig_getplci, 1, 0, 0 },
{ NULL, NULL, 0 }
};
@ -7324,11 +7326,15 @@ static int pbx_capicommand_exec(struct ast_channel *chan, void *data)
return -1;
}
if (chan != NULL) {
#ifdef CC_AST_HAS_VERSION_1_4
u = ast_module_user_add(chan);
u = ast_module_user_add(chan);
#else
LOCAL_USER_ADD(u);
LOCAL_USER_ADD(u);
#endif
} else {
u = NULL;
}
s = ast_strdupa(data);
stringp = s;
@ -7342,18 +7348,21 @@ static int pbx_capicommand_exec(struct ast_channel *chan, void *data)
break;
capicmd++;
}
if (!capicmd->cmd) {
if ((capicmd->cmd == NULL) ||
((chan == NULL) && (capicmd->notchannelrelated == 0))) {
if (chan != NULL) {
#ifdef CC_AST_HAS_VERSION_1_4
ast_module_user_remove(u);
ast_module_user_remove(u);
#else
LOCAL_USER_REMOVE(u);
LOCAL_USER_REMOVE(u);
#endif
cc_log(LOG_WARNING, "Unknown command '%s' for capicommand\n",
command);
}
cc_log(LOG_WARNING, "%s command '%s' for capicommand\n",
(capicmd->cmd == NULL) ? "Unknown" : "Channel required for", command);
return -1;
}
if (chan->tech != &capi_tech) {
if ((chan != NULL) && (chan->tech != &capi_tech)) {
if (capicmd->capionly != 0) {
struct capi_pvt* resource_plci = pbx_check_resource_plci (chan);
@ -7373,12 +7382,15 @@ static int pbx_capicommand_exec(struct ast_channel *chan, void *data)
}
res = (capicmd->cmd)(chan, params);
if (chan != NULL) {
#ifdef CC_AST_HAS_VERSION_1_4
ast_module_user_remove(u);
ast_module_user_remove(u);
#else
LOCAL_USER_REMOVE(u);
LOCAL_USER_REMOVE(u);
#endif
}
return res;
}

View File

@ -52,6 +52,7 @@
#ifdef DIVA_STREAMING
struct _diva_stream_scheduling_entry;
#endif
struct _pbx_capi_conference_bridge;
#define CAPI_MAX_CONTROLLERS 64
#define CAPI_MAX_B3_BLOCKS 7
@ -561,6 +562,8 @@ struct capi_pvt {
#ifdef DIVA_STREAMING
struct _diva_stream_scheduling_entry* diva_stream_entry;
#endif
/* Connection between two conference rooms. NULL PLCI */
struct capi_pvt *bridgePeer;
/*! Next channel in list */
struct capi_pvt *next;

View File

@ -364,7 +364,7 @@ static void del_chat_member(struct capichat_s *room)
/*
* add a new chat member
*/
static struct capichat_s *add_chat_member(char *roomname, struct capi_pvt *i, room_member_type_t room_member_type)
static struct capichat_s *add_chat_member(const char *roomname, struct capi_pvt *i, room_member_type_t room_member_type)
{
struct capichat_s *room = NULL;
struct capichat_s *tmproom;
@ -1318,3 +1318,81 @@ void pbx_capi_unlock_chat_rooms(void)
cc_mutex_unlock(&chat_lock);
}
/*!
\brief Connect two conference rooms.
*/
static struct capi_pvt*
pbx_capi_create_conference_bridge(const char* mainName,
unsigned long long mainController,
const char* additionalName,
unsigned long long additionalController)
{
struct capi_pvt *capi_ifc[2] = { 0, 0 };
struct capichat_s *room[sizeof(capi_ifc)/sizeof(capi_ifc[0])] = { 0, 0 };
const char* name[sizeof(capi_ifc)/sizeof(capi_ifc[0])] = { mainName, additionalName };
unsigned long long controller[sizeof(capi_ifc)/sizeof(capi_ifc[0])] = { mainController, additionalController };
int error, i;
if ((mainName == 0) || (additionalName == 0) ||
(mainController == 0) || (additionalController == 0))
return NULL;
pbx_capi_nulliflist_lock();
for (i = 0, error = 0; (error == 0) && (i < sizeof(name)/sizeof(name[0])); i++) {
capi_ifc[i] = capi_mknullif(NULL, controller[i]);
error |= (capi_ifc[i] == NULL);
}
if (error == 0) {
capi_ifc[0]->bridgePeer = capi_ifc[1];
capi_ifc[1]->bridgePeer = capi_ifc[0];
}
pbx_capi_nulliflist_unlock();
for (i = 0; (error == 0) && (i < sizeof(name)/sizeof(name[0])); i++) {
room[i] = add_chat_member(name[i], capi_ifc[i], RoomMemberOperator);
error |= (room[i] == NULL);
}
if (error != 0) {
for (i = 0; i < sizeof(name)/sizeof(name[0]); i++) {
if (room[i] != 0) {
del_chat_member(room[i]);
}
if (capi_ifc[i] != 0) {
capi_remove_nullif(capi_ifc[i]);
capi_ifc[i] = 0;
}
}
}
return capi_ifc[0];
}
/*!
\brief Connect two conference rooms. "room,controller,room,controller";
*/
int pbx_capi_chat_connect(struct ast_channel *c, char *param) {
char* rooms[2];
unsigned long long controllers[sizeof(rooms)/sizeof(rooms[0])] = { 0UL, 0UL };
struct capi_pvt *capi_ifc;
int i;
for (i = 0; i < sizeof(rooms)/sizeof(rooms[0]); i++) {
char* v;
rooms[i] = strsep(&param, COMMANDSEPARATOR);
v = pbx_capi_strsep_controller_list (&param);
controllers[i] = ast_get_group(v);
}
capi_ifc = pbx_capi_create_conference_bridge(rooms[0], controllers[0], rooms[1], controllers[1]);
if (capi_ifc != NULL) {
cc_verbose(3, 0, VERBOSE_PREFIX_3 CC_MESSAGE_NAME
"Chat connect '%s' <-> '%s'\n", rooms[0], rooms[1]);
} else {
cc_log(LOG_WARNING, "Chat failed to connect '%s' <-> '%s'\n", rooms[0], rooms[1]);
}
return ((capi_ifc != NULL) ? 0 : -1);
}

View File

@ -26,6 +26,7 @@ extern int pbxcli_capi_chatinfo(int fd, int argc, char *argv[]);
extern int pbx_capi_chat_command (struct ast_channel *c, char *param);
extern int pbx_capi_chat_mute(struct ast_channel *c, char *param);
extern int pbx_capi_chat_play(struct ast_channel *c, char *param);
extern int pbx_capi_chat_connect(struct ast_channel *c, char *param);
int pbx_capi_chat_remove_user(const char* room, const char* name);
struct capichat_s;

View File

@ -63,6 +63,11 @@ int pbx_capi_management_capicommand(const char *requiredChannelName, const char
return -3;
}
if (strcmp(requiredChannelName, "none") == 0) {
int ret = (pbx_capi_cli_exec_capicommand(NULL, chancapiCommand) == 0) ? 0 : -1;
return (ret);
}
for (ifc_type = 0; ifc_type < sizeof(data)/sizeof(data[0]); ifc_type++) {
search_loops = 10;
do {

View File

@ -191,7 +191,7 @@ struct capi_pvt *capi_mknullif(struct ast_channel *c, unsigned long long control
cc_mutex_init(&tmp->lock);
ast_cond_init(&tmp->event_trigger, NULL);
snprintf(tmp->name, sizeof(tmp->name) - 1, "%s-NULLPLCI", c->name);
snprintf(tmp->name, sizeof(tmp->name) - 1, "%s-NULLPLCI", (c != 0) ? c->name : "BRIDGE");
snprintf(tmp->vname, sizeof(tmp->vname) - 1, "%s", tmp->name);
tmp->channeltype = CAPI_CHANNELTYPE_NULL;
@ -214,9 +214,11 @@ struct capi_pvt *capi_mknullif(struct ast_channel *c, unsigned long long control
tmp->txgain = 1.0;
capi_gains(&tmp->g, 1.0, 1.0);
if (!(capi_create_reader_writer_pipe(tmp))) {
ast_free(tmp);
return NULL;
if (c != 0) {
if (!(capi_create_reader_writer_pipe(tmp))) {
ast_free(tmp);
return NULL;
}
}
tmp->bproto = CC_BPROTO_TRANSPARENT;
@ -1646,3 +1648,31 @@ void pbx_capi_nulliflist_unlock(void)
cc_mutex_unlock(&nullif_lock);
}
/*!
\brief get list of controllers. Stop parsing
after non digit detected after separator
character or end of string is reached
*/
char* pbx_capi_strsep_controller_list (char** param)
{
char *src, *p;
if ((param == NULL) || (*param == NULL) || (**param == 0))
return NULL;
if (strchr(*param, '|') != NULL)
return (strsep(param, "|"));
src = *param;
p = src - 1;
do {
p = strchr(p+1, ',');
} while ((p != NULL) && (isdigit(p[1]) != 0));
if (p != NULL)
*p++ = 0;
*param = p;
return src;
}

View File

@ -62,6 +62,7 @@ extern int capi_verify_resource_plci(const struct capi_pvt *i);
extern const char* pbx_capi_get_cid (const struct ast_channel* c, const char *notAvailableVisual);
extern const char* pbx_capi_get_callername (const struct ast_channel* c, const char *notAvailableVisual);
const char* pbx_capi_get_connectedname (const struct ast_channel* c, const char *notAvailableVisual);
char* pbx_capi_strsep_controller_list (char** param);
#define capi_number(data, strip) \
capi_number_func(data, strip, alloca(AST_MAX_EXTENSION))

View File

@ -78,8 +78,24 @@ static int divaStreamingMessageRx (void* user_context, dword message, dword leng
if (likely(process_indication != 0)) {
if (likely(Ind == 8)) {
if (likely(pE->i != 0 && pE->i->NCCI != 0))
capidev_handle_data_b3_indication_vector (pE->i, vind, vind_nr);
if (likely(pE->i != 0 && pE->i->NCCI != 0)) {
if (pE->i->bridgePeer != 0) {
struct capi_pvt* bridgePeer = pE->i->bridgePeer;
if (bridgePeer->NCCI != 0 && bridgePeer->diva_stream_entry != 0 &&
bridgePeer->diva_stream_entry->diva_stream_state == DivaStreamActive &&
bridgePeer->diva_stream_entry->diva_stream->get_tx_free (bridgePeer->diva_stream_entry->diva_stream) > 2*CAPI_MAX_B3_BLOCK_SIZE+128) {
dword i = 0, k = 0, b3len;
byte b3buf[CAPI_MAX_B3_BLOCK_SIZE];
b3len = diva_streaming_read_vector_data(vind, vind_nr, &i, &k, b3buf, CAPI_MAX_B3_BLOCK_SIZE);
bridgePeer->diva_stream_entry->diva_stream->write (bridgePeer->diva_stream_entry->diva_stream,
8U << 8 | DIVA_STREAM_MESSAGE_TX_IDI_REQUEST,
b3buf, b3len);
bridgePeer->diva_stream_entry->diva_stream->flush_stream(bridgePeer->diva_stream_entry->diva_stream);
}
} else {
capidev_handle_data_b3_indication_vector (pE->i, vind, vind_nr);
}
}
} else {
dword i = 0, k = 0;
word data_length;