Group based conference, remove groups only if enture conference is in idle state, clean up

This commit is contained in:
MelwareDE 2010-12-14 16:28:18 +00:00
parent 3c491e7f65
commit 6decf34007
5 changed files with 157 additions and 75 deletions

View File

@ -4497,16 +4497,18 @@ static void capidev_handle_data_b3_indication(
return_on_no_interface("DATA_B3_IND");
if ((i->bridgePeer != NULL)
if (i->virtualBridgePeer != 0) {
if ((i->bridgePeer != NULL)
#ifdef DIVA_STREAMING
&& (i->diva_stream_entry == 0)
&& (i->bridgePeer->diva_stream_entry == 0)
&& (i->diva_stream_entry == 0)
&& (i->bridgePeer->diva_stream_entry == 0)
#endif
) {
if (i->bridgePeer->NCCI != 0) {
i->bridgePeer->send_buffer_handle++;
capi_sendf(NULL, 0, CAPI_DATA_B3_REQ, i->bridgePeer->NCCI, get_capi_MessageNumber(),
"dwww", b3buf, b3len, i->bridgePeer->send_buffer_handle, 0);
) {
if (i->bridgePeer->NCCI != 0) {
i->bridgePeer->send_buffer_handle++;
capi_sendf(NULL, 0, CAPI_DATA_B3_REQ, i->bridgePeer->NCCI, get_capi_MessageNumber(),
"dwww", b3buf, b3len, i->bridgePeer->send_buffer_handle, 0);
}
}
return;
}

View File

@ -563,6 +563,7 @@ struct capi_pvt {
struct _diva_stream_scheduling_entry* diva_stream_entry;
#endif
/* Connection between two conference rooms. NULL PLCI */
int virtualBridgePeer;
struct capi_pvt *bridgePeer;
/*! Next channel in list */

View File

@ -88,13 +88,12 @@ static size_t pbx_capi_create_full_room_name(const char* roomName, unsigned int
static int pbx_capi_chat_get_group_controller(const char* roomName, unsigned int group);
static unsigned int pbx_capi_find_group (const char* roomName, unsigned long long controllers);
static unsigned int pbx_capi_add_group_user(const char* roomName, unsigned int groupNumber);
static unsigned int pbx_capi_remove_group_user(const char* roomName,
unsigned int groupNumber,
struct capichat_s** mainGroup,
struct capichat_s** additionalGroup);
static unsigned int pbx_capi_remove_group_user(const char* roomName, unsigned int groupNumber);
static void pbx_capi_chat_enter_bridge_modify_state(void);
static void pbx_capi_chat_leave_bridge_modify_state(void);
static struct capichat_s* pbx_capi_get_room_bridge(const char* roomName);
static struct capichat_s* pbx_capi_get_group_main_bridge(struct capi_pvt* mainPLCI);
static int pbx_capi_is_bridge_idle(const char* roomName);
static void pbx_capi_cleanup_bridge(const char* roomName, unsigned int groupNumber);
/*
@ -1544,26 +1543,26 @@ static int pbx_capi_chat_get_group_controller(const char* roomName, unsigned int
/*!
\brief Find froup with max free number
*/
static unsigned int pbx_capi_chat_find_max_group (const char* roomName) {
static unsigned int pbx_capi_chat_find_free_group (const char* roomName) {
struct capichat_s *currentRoom;
char* roomNameTemplate = alloca(strlen(roomName) + strlen(PBX_CHAT_GROUP_PREFIX) + 1);
unsigned int maxGroup = 1;
unsigned int selectedGroup = 1;
strcpy(roomNameTemplate, roomName);
strcat(roomNameTemplate, PBX_CHAT_GROUP_PREFIX);
cc_mutex_lock(&chat_lock);
for (currentRoom = chat_list; currentRoom != 0; currentRoom = currentRoom->next) {
if ((currentRoom->group > maxGroup) &&
for (currentRoom = chat_list, selectedGroup = 1; currentRoom != 0; currentRoom = currentRoom->next) {
if ((currentRoom->group >= selectedGroup) &&
(strlen(roomNameTemplate) < strlen(currentRoom->name)) &&
(memcmp(currentRoom->name, roomNameTemplate, strlen(roomNameTemplate)) == 0) &&
((unsigned int)atoi(&currentRoom->name[strlen(roomNameTemplate)]) == currentRoom->group)) {
maxGroup = currentRoom->group;
selectedGroup = currentRoom->group;
}
}
cc_mutex_unlock(&chat_lock);
return (maxGroup+1);
return (selectedGroup+1);
}
static void pbx_capi_chat_enter_bridge_modify_state(void)
@ -1610,7 +1609,7 @@ static unsigned int pbx_capi_find_group (const char* roomName, unsigned long lon
int controller = pbx_capi_chat_get_group_controller(roomName, 1);
unsigned long long mainController = controllers;
selectedGroup = pbx_capi_chat_find_max_group (roomName);
selectedGroup = pbx_capi_chat_find_free_group (roomName);
if (controller > 0) {
mainController = (1LU << (controller - 1));
@ -1623,19 +1622,24 @@ static unsigned int pbx_capi_find_group (const char* roomName, unsigned long lon
return selectedGroup;
}
/*
\brief Return responsible for group bridge
*/
static struct capichat_s* pbx_capi_get_group_bridge(const char* roomName, unsigned int groupNumber)
{
struct capichat_s *currentRoom;
char* roomNameTemplate = alloca(strlen(roomName) + strlen(PBX_CHAT_GROUP_PREFIX) + 1);
size_t roomNameTemplateLen;
strcpy(roomNameTemplate, roomName);
strcat(roomNameTemplate, PBX_CHAT_GROUP_PREFIX);
roomNameTemplateLen = strlen(roomNameTemplate);
for (currentRoom = chat_list; currentRoom != 0; currentRoom = currentRoom->next) {
if ((currentRoom->i != NULL) &&
(strlen(roomNameTemplate) < strlen(currentRoom->name)) &&
(memcmp(currentRoom->name, roomNameTemplate, strlen(roomNameTemplate)) == 0) &&
((unsigned int)atoi(&currentRoom->name[strlen(roomNameTemplate)]) == currentRoom->group) &&
if ((currentRoom->group == groupNumber) && (currentRoom->i != NULL) &&
(roomNameTemplateLen < strlen(currentRoom->name)) &&
(memcmp(currentRoom->name, roomNameTemplate, roomNameTemplateLen) == 0) &&
((unsigned int)atoi(&currentRoom->name[roomNameTemplateLen]) == currentRoom->group) &&
(currentRoom->i->used == NULL) && (currentRoom->i->bridgePeer != NULL)) {
return currentRoom;
}
@ -1644,17 +1648,75 @@ static struct capichat_s* pbx_capi_get_group_bridge(const char* roomName, unsign
return NULL;
}
static struct capichat_s* pbx_capi_get_group_main_bridge(struct capi_pvt* mainPLCI)
/*!
\brief Returns true if bridge is idle
*/
static int pbx_capi_is_bridge_idle(const char* roomName)
{
struct capichat_s *currentRoom;
char* roomNameTemplate = alloca(strlen(roomName) + strlen(PBX_CHAT_GROUP_PREFIX) + 1);
size_t roomNameTemplateLen;
int bridgeIdle;
for (currentRoom = chat_list; currentRoom != 0; currentRoom = currentRoom->next) {
if (currentRoom->i == mainPLCI) {
return (currentRoom);
strcpy(roomNameTemplate, roomName);
strcat(roomNameTemplate, PBX_CHAT_GROUP_PREFIX);
roomNameTemplateLen = strlen(roomNameTemplate);
cc_mutex_lock(&chat_lock);
for (currentRoom = chat_list, bridgeIdle = 1;
((bridgeIdle != 0) && (currentRoom != 0));
currentRoom = currentRoom->next) {
if ((currentRoom->group > 1) && (currentRoom->groupUsers != 0) && (currentRoom->i != NULL) &&
(roomNameTemplateLen < strlen(currentRoom->name)) &&
(memcmp(currentRoom->name, roomNameTemplate, roomNameTemplateLen) == 0) &&
((unsigned int)atoi(&currentRoom->name[roomNameTemplateLen]) == currentRoom->group) &&
(currentRoom->i->used == NULL) && (currentRoom->i->bridgePeer != NULL)) {
bridgeIdle = 0;
}
}
cc_mutex_unlock(&chat_lock);
return NULL;
return bridgeIdle;
}
static struct capichat_s* pbx_capi_get_room_bridge(const char* roomName)
{
struct capichat_s *currentRoom;
char* roomNameTemplate = alloca(strlen(roomName) + strlen(PBX_CHAT_GROUP_PREFIX) + 1);
size_t roomNameTemplateLen;
strcpy(roomNameTemplate, roomName);
strcat(roomNameTemplate, PBX_CHAT_GROUP_PREFIX);
roomNameTemplateLen = strlen(roomNameTemplate);
cc_mutex_lock(&chat_lock);
for (currentRoom = chat_list; currentRoom != 0; currentRoom = currentRoom->next) {
if ((currentRoom->group > 1) && (currentRoom->i != NULL) &&
(roomNameTemplateLen < strlen(currentRoom->name)) &&
(memcmp(currentRoom->name, roomNameTemplate, roomNameTemplateLen) == 0) &&
((unsigned int)atoi(&currentRoom->name[roomNameTemplateLen]) == currentRoom->group) &&
(currentRoom->i->used == NULL) && (currentRoom->i->bridgePeer != NULL)) {
break;
}
}
cc_mutex_unlock(&chat_lock);
return currentRoom;
}
static struct capichat_s* pbx_capi_get_group_main_bridge(struct capi_pvt* mainPLCI)
{
struct capichat_s *currentRoom = NULL;
cc_mutex_lock(&chat_lock);
for (currentRoom = chat_list; currentRoom != 0; currentRoom = currentRoom->next) {
if (currentRoom->i == mainPLCI) {
break;
}
}
cc_mutex_unlock(&chat_lock);
return currentRoom;
}
static unsigned int pbx_capi_add_group_user(const char* roomName, unsigned int groupNumber)
@ -1667,24 +1729,30 @@ static unsigned int pbx_capi_add_group_user(const char* roomName, unsigned int g
if (groupBridge != NULL) {
groupBridge->groupUsers++;
ret = groupBridge->groupUsers;
{
size_t mainFullNameLength = pbx_capi_create_full_room_name(roomName, 1, NULL, 0);
size_t additionalFullNameLength = pbx_capi_create_full_room_name(roomName, groupNumber, NULL, 0);
char* mainFullName = alloca(mainFullNameLength);
char* additionalFullName = alloca(additionalFullNameLength);
pbx_capi_create_full_room_name(roomName, 1, mainFullName, mainFullNameLength);
pbx_capi_create_full_room_name(roomName, groupNumber, additionalFullName, additionalFullNameLength);
cc_verbose(2, 0, VERBOSE_PREFIX_2 CC_MESSAGE_NAME
" Add bridge user (%u) '%s' <-> '%s'\n", ret, mainFullName, additionalFullName);
}
}
cc_mutex_unlock(&chat_lock);
return ret;
}
static unsigned int pbx_capi_remove_group_user(const char* roomName,
unsigned int groupNumber,
struct capichat_s** mainGroup,
struct capichat_s** additionalGroup)
static unsigned int pbx_capi_remove_group_user(const char* roomName, unsigned int groupNumber)
{
struct capichat_s* groupBridge;
unsigned int ret = 0;
*mainGroup = NULL;
*additionalGroup = NULL;
cc_mutex_lock(&chat_lock);
groupBridge = pbx_capi_get_group_bridge(roomName, groupNumber);
if (groupBridge != NULL) {
@ -1692,10 +1760,6 @@ static unsigned int pbx_capi_remove_group_user(const char* roomName,
groupBridge->groupUsers--;
}
ret = groupBridge->groupUsers;
if (ret == 0) {
*mainGroup = pbx_capi_get_group_main_bridge(groupBridge->i->bridgePeer);
*additionalGroup = groupBridge;
}
}
cc_mutex_unlock(&chat_lock);
@ -1714,43 +1778,53 @@ static void pbx_capi_cleanup_bridge(const char* roomName, unsigned int groupNumb
size_t additionalFullNameLength = pbx_capi_create_full_room_name(roomName, groupNumber, NULL, 0);
char* mainFullName = alloca(mainFullNameLength);
char* additionalFullName = alloca(additionalFullNameLength);
struct capichat_s* mainGroup;
struct capichat_s* additionalGroup;
pbx_capi_create_full_room_name(roomName, 1, mainFullName, mainFullNameLength);
pbx_capi_create_full_room_name(roomName, groupNumber, additionalFullName, additionalFullNameLength);
pbx_capi_chat_enter_bridge_modify_state();
bridgeUsers = pbx_capi_remove_group_user(roomName, groupNumber, &mainGroup, &additionalGroup);
bridgeUsers = pbx_capi_remove_group_user(roomName, groupNumber);
cc_verbose(2, 0, VERBOSE_PREFIX_2 CC_MESSAGE_NAME
" Delete bridge user (%u) '%s' <-> '%s'\n", bridgeUsers, mainFullName, additionalFullName);
if (bridgeUsers == 0) {
struct capi_pvt *mainPLCI = mainGroup->i, *additionalPLCI = additionalGroup->i;
cc_verbose(2, 0, VERBOSE_PREFIX_2 CC_MESSAGE_NAME
" Delete bridge '%s' <-> '%s'\n", mainFullName, additionalFullName);
/*
Delecte bridge between conference room groups
Delecte bridge between conference room groups.
To reduce the load at the central bridge while the conference running
the bridge is remoced only if all bridges are in idle state
*/
if (pbx_capi_is_bridge_idle(roomName) != 0) {
struct capichat_s* additionalGroup;
del_chat_member(additionalGroup);
del_chat_member(mainGroup);
while ((additionalGroup = pbx_capi_get_room_bridge(roomName)) != 0) {
struct capichat_s* mainGroup = pbx_capi_get_group_main_bridge(additionalGroup->i->bridgePeer);
struct capi_pvt *mainPLCI = mainGroup->i, *additionalPLCI = additionalGroup->i;
pbx_capi_create_full_room_name(roomName, additionalGroup->group, additionalFullName, additionalFullNameLength);
cc_verbose(2, 0, VERBOSE_PREFIX_2 CC_MESSAGE_NAME
" Delete bridge '%s' <-> '%s'\n", mainFullName, additionalFullName);
del_chat_member(additionalGroup);
del_chat_member(mainGroup);
#ifdef DIVA_STREAMING
capi_DivaStreamLock();
capi_DivaStreamLock();
#endif
cc_mutex_lock(&mainPLCI->lock);
cc_mutex_lock(&additionalPLCI->lock);
mainPLCI->bridgePeer = NULL;
additionalPLCI->bridgePeer = NULL;
cc_mutex_unlock(&additionalPLCI->lock);
cc_mutex_unlock(&mainPLCI->lock);
cc_mutex_lock(&mainPLCI->lock);
cc_mutex_lock(&additionalPLCI->lock);
mainPLCI->bridgePeer = NULL;
additionalPLCI->bridgePeer = NULL;
cc_mutex_unlock(&additionalPLCI->lock);
cc_mutex_unlock(&mainPLCI->lock);
#ifdef DIVA_STREAMING
capi_DivaStreamUnLock();
capi_DivaStreamUnLock();
#endif
capi_remove_nullif(mainPLCI);
capi_remove_nullif(additionalPLCI);
} else {
cc_verbose(2, 0, VERBOSE_PREFIX_2 CC_MESSAGE_NAME
" Delete bridge user (%u) '%s' <-> '%s'\n", bridgeUsers, mainFullName, additionalFullName);
capi_remove_nullif(mainPLCI);
capi_remove_nullif(additionalPLCI);
}
}
}
pbx_capi_chat_leave_bridge_modify_state();
}
}

View File

@ -198,6 +198,8 @@ struct capi_pvt *capi_mknullif(struct ast_channel *c, unsigned long long control
tmp->used = c;
tmp->peer = c;
if (c == NULL)
tmp->virtualBridgePeer = 1;
tmp->cip = CAPI_CIPI_SPEECH;
tmp->transfercapability = PRI_TRANS_CAP_SPEECH;

View File

@ -79,20 +79,23 @@ 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)) {
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 {
DBG_ERR(("DROP BRIDGE PACKET"))
if (pE->i->virtualBridgePeer != 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 {
DBG_ERR(("DROP BRIDGE PACKET"))
}
}
} else {
capidev_handle_data_b3_indication_vector (pE->i, vind, vind_nr);