Add chat_connect to interconnect two chat roouss using NULL PLCI
parent
29581c9637
commit
a60f4cf67a
130
chan_capi.c
130
chan_capi.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(¶m, COMMANDSEPARATOR);
|
||||
v = pbx_capi_strsep_controller_list (¶m);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue