add switch_ivr_enterprise_originate optional new dimension to originate strings every element in :_: separated list in originate strings will fire in a dedicated thread and can contain their own {} and , and | lists

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@15455 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2009-11-12 22:21:30 +00:00
parent 7d0980232e
commit 06a68fce64
4 changed files with 221 additions and 4 deletions

View File

@ -409,6 +409,19 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
switch_originate_flag_t flags
);
SWITCH_DECLARE(switch_status_t) switch_ivr_enterprise_originate(switch_core_session_t *session,
switch_core_session_t **bleg,
switch_call_cause_t *cause,
const char *bridgeto,
uint32_t timelimit_sec,
const switch_state_handler_table_t *table,
const char *cid_name_override,
const char *cid_num_override,
switch_caller_profile_t *caller_profile_override,
switch_event_t *ovars,
switch_originate_flag_t flags
);
SWITCH_DECLARE(void) switch_ivr_bridge_display(switch_core_session_t *session, switch_core_session_t *peer_session);
/*!

View File

@ -517,6 +517,7 @@ SWITCH_DECLARE(switch_time_t) switch_str_time(const char *in);
\return the number of elements added to the array
*/
SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char **array, unsigned int arraylen);
SWITCH_DECLARE(unsigned int) switch_separate_string_string(char *buf, char *delim, char **array, unsigned int arraylen);
SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str);
SWITCH_DECLARE(char *) switch_strip_spaces(const char *str);

View File

@ -1134,6 +1134,180 @@ static switch_status_t setup_ringback(originate_global_t *oglobals,
}
#define OSEP ":_:"
#define MAX_PEERS 128
typedef struct {
switch_core_session_t *session;
switch_core_session_t *bleg;
switch_call_cause_t cause;
const char *bridgeto;
uint32_t timelimit_sec;
const switch_state_handler_table_t *table;
const char *cid_name_override;
const char *cid_num_override;
switch_caller_profile_t *caller_profile_override;
switch_event_t *ovars;
switch_originate_flag_t flags;
switch_status_t status;
int done;
switch_thread_t *thread;
} enterprise_originate_handle_t;
static void *SWITCH_THREAD_FUNC enterprise_originate_thread(switch_thread_t *thread, void *obj)
{
enterprise_originate_handle_t *handle = (enterprise_originate_handle_t *) obj;
handle->done = 0;
handle->status = switch_ivr_originate(NULL, &handle->bleg, &handle->cause,
handle->bridgeto, handle->timelimit_sec,
handle->table,
handle->cid_name_override,
handle->cid_num_override,
handle->caller_profile_override,
handle->ovars,
handle->flags
);
handle->done = 1;
return NULL;
}
SWITCH_DECLARE(switch_status_t) switch_ivr_enterprise_originate(switch_core_session_t *session,
switch_core_session_t **bleg,
switch_call_cause_t *cause,
const char *bridgeto,
uint32_t timelimit_sec,
const switch_state_handler_table_t *table,
const char *cid_name_override,
const char *cid_num_override,
switch_caller_profile_t *caller_profile_override,
switch_event_t *ovars,
switch_originate_flag_t flags
)
{
int x_argc;
char *x_argv[MAX_PEERS] = { 0 };
enterprise_originate_handle_t *hp = NULL, handles[MAX_PEERS] = { { 0 } };
int i;
switch_caller_profile_t *cp = NULL;
switch_channel_t *channel = NULL;
char *data;
switch_status_t status = SWITCH_STATUS_FALSE;
switch_threadattr_t *thd_attr = NULL;
int running = 0;
switch_status_t tstatus = SWITCH_STATUS_FALSE;
switch_memory_pool_t *pool;
switch_event_header_t *hi = NULL;
switch_core_new_memory_pool(&pool);
if (zstr(bridgeto)) {
*cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
data = switch_core_strdup(pool, bridgeto);
if (!(x_argc = switch_separate_string_string(data, OSEP, x_argv, MAX_PEERS))) {
*cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
if (session) {
channel = switch_core_session_get_channel(session);
cp = switch_channel_get_caller_profile(channel);
}
switch_threadattr_create(&thd_attr, pool);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
for(i = 0; i < x_argc; i++) {
handles[i].session = session;
handles[i].bleg = NULL;
handles[i].cause = 0;
handles[i].bridgeto = x_argv[i];
handles[i].timelimit_sec = timelimit_sec;
handles[i].table = table;
handles[i].cid_name_override = cid_name_override;
handles[i].cid_num_override = cid_num_override;
handles[i].caller_profile_override = cp;
if (channel) {
switch_channel_get_variables(channel, &handles[i].ovars);
} else {
switch_event_create_plain(&handles[i].ovars, SWITCH_EVENT_CHANNEL_DATA);
}
if (ovars) {
for (hi = ovars->headers; hi; hi = hi->next) {
switch_event_add_header_string(handles[i].ovars, SWITCH_STACK_BOTTOM, hi->name, hi->value);
}
}
handles[i].flags = flags;
switch_thread_create(&handles[i].thread, thd_attr, enterprise_originate_thread, &handles[i], pool);
}
for(;;) {
running = 0;
for(i = 0; i < x_argc; i++) {
if (handles[i].done == 0) {
running++;
} else if (handles[i].done == 1) {
if (handles[i].status == SWITCH_STATUS_SUCCESS) {
hp = &handles[i];
goto done;
} else {
handles[i].done = 2;
}
}
switch_cond_next();
}
if (!running) {
break;
}
}
done:
for(i = 0; i < x_argc; i++) {
if (hp && hp == &handles[i]) {
continue;
}
if (handles[i].bleg) {
switch_channel_hangup(switch_core_session_get_channel(handles[i].bleg), SWITCH_CAUSE_LOSE_RACE);
switch_core_session_rwunlock(handles[i].bleg);
}
handles[i].cause = SWITCH_CAUSE_LOSE_RACE;
switch_thread_join(&tstatus, handles[i].thread);
switch_event_destroy(&handles[i].ovars);
}
if (hp) {
*cause = hp->cause;
status = hp->status;
*bleg = hp->bleg;
switch_thread_join(&tstatus, hp->thread);
switch_event_destroy(&hp->ovars);
}
end:
switch_core_destroy_memory_pool(&pool);
return status;
}
#define peer_eligible(_peer) (_peer && !(switch_channel_test_flag(_peer, CF_TRANSFER) || \
switch_channel_test_flag(_peer, CF_REDIRECT) || \
@ -1141,7 +1315,7 @@ static switch_status_t setup_ringback(originate_global_t *oglobals,
switch_channel_get_state(_peer) == CS_RESET || \
!switch_channel_test_flag(_peer, CF_ORIGINATING)))
#define MAX_PEERS 128
SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *session,
switch_core_session_t **bleg,
switch_call_cause_t *cause,
@ -1195,6 +1369,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
const char *holding = NULL;
const char *export_vars = NULL;
if (strstr(bridgeto, OSEP)) {
return switch_ivr_enterprise_originate(session, bleg, cause, bridgeto, timelimit_sec, table, cid_name_override, cid_num_override,
caller_profile_override, ovars, flags);
}
oglobals.ringback_ok = 1;
if (session) {
@ -1240,8 +1421,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
oglobals.idx = IDX_NADA;
oglobals.early_ok = 1;
*bleg = NULL;
switch_zmalloc(write_frame.data, SWITCH_RECOMMENDED_BUFFER_SIZE);
@ -2088,7 +2267,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
oglobals.ringback_ok = 0;
}
while ((!caller_channel || switch_channel_ready(caller_channel) || switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) &&
*cause = 0;
while (*cause == 0 && ((!caller_channel || switch_channel_ready(caller_channel) || switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE))) &&
check_channel_status(&oglobals, originate_status, and_argc)) {
time_t elapsed = switch_epoch_time_now(NULL) - start;
@ -2252,6 +2432,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
}
if (*cause) {
force_reason = *cause;
}
notready:
if (caller_channel) {

View File

@ -1589,6 +1589,25 @@ static char *cleanup_separated_string(char *str, char delim)
return start;
}
SWITCH_DECLARE(unsigned int) switch_separate_string_string(char *buf, char *delim, char **array, unsigned int arraylen)
{
unsigned int count = 0;
char *d;
size_t dlen = strlen(delim);
array[count++] = buf;
while (count < arraylen && array[count-1]) {
if ((d = strstr(array[count-1], delim))) {
*d = '\0';
d += dlen;
array[count++] = d;
} else break;
}
return count;
}
/* Separate a string using a delimiter that is not a space */
static unsigned int separate_string_char_delim(char *buf, char delim, char **array, unsigned int arraylen)
{