switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
switch_call_cause_t *cancel_cause)
{
- switch_xml_t x_user = NULL, x_param, x_params;
+ switch_xml_t x_user = NULL, x_param, x_params, x_callfwd;
char *user = NULL, *domain = NULL, *dup_domain = NULL, *dialed_user = NULL;
- const char *dest = NULL;
+ char *dest = NULL;
switch_call_cause_t cause = SWITCH_CAUSE_NONE;
unsigned int timelimit = SWITCH_DEFAULT_TIMEOUT;
switch_channel_t *new_channel = NULL;
char stupid[128] = "";
const char *skip = NULL, *var = NULL;
switch_core_session_t *a_session = NULL, *e_session = NULL;
+ cJSON * ctx = NULL;
+ const char *endpoint_dial = NULL;
+ const char *callforward_dial = NULL;
+ const char *failover_dial = NULL;
+ char *b_failover_dial = NULL;
+ const char *endpoint_separator = NULL;
+ const char *varval = NULL;
+ char *d_dest = NULL;
+ switch_channel_t *channel = NULL;
+ switch_originate_flag_t myflags = SOF_NONE;
+ char *cid_name_override = NULL;
+ char *cid_num_override = NULL;
+ switch_event_t *event = NULL;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+
if (zstr(outbound_profile->destination_number)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "NO DESTINATION NUMBER\n");
goto done;
}
+ if (var_event) {
+ const char * str_ctx = switch_event_get_header(var_event, "kz-endpoint-runtime-context");
+ if ( str_ctx ) {
+ ctx = cJSON_Parse(str_ctx);
+ if (ctx) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call context parsed => %s\n", str_ctx);
+ }
+ }
+ }
+
if ((x_params = switch_xml_child(x_user, "variables"))) {
for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
const char *pvar = switch_xml_attr_soft(x_param, "name");
const char *pvar = switch_xml_attr_soft(x_param, "name");
const char *val = switch_xml_attr(x_param, "value");
- if (!strcasecmp(pvar, "dial-string")) {
- dest = val;
+ if (!strcasecmp(pvar, "endpoint-dial-string")) {
+ endpoint_dial = val;
+ } else if (!strcasecmp(pvar, "callforward-dial-string")) {
+ callforward_dial = val;
+ } else if (!strcasecmp(pvar, "endpoint-separator")) {
+ endpoint_separator = val;
} else if (!strncasecmp(pvar, "dial-var-", 9)) {
if (!var_event) {
switch_event_create(&var_event, SWITCH_EVENT_GENERAL);
}
}
+ x_callfwd = switch_xml_child(x_user, "call-forward");
+ if (x_callfwd) {
+ switch_bool_t call_fwd_is_substitute = SWITCH_FALSE,
+ call_fwd_is_failover = SWITCH_FALSE,
+ call_fwd_direct_calls_only = SWITCH_FALSE,
+ call_fwd_is_valid = SWITCH_TRUE;
+ for (x_param = switch_xml_child(x_callfwd, "variable"); x_param; x_param = x_param->next) {
+ const char *var = switch_xml_attr_soft(x_param, "name");
+ const char *val = switch_xml_attr(x_param, "value");
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "cfw %s => %s\n", var, val);
+ if (!strcasecmp(var, "Is-Substitute")) {
+ call_fwd_is_substitute = switch_true(val);
+ } else if (!strcasecmp(var, "Is-Failover")) {
+ call_fwd_is_failover = switch_true(val);
+ } else if (!strcasecmp(var, "Direct-Calls-Only")) {
+ call_fwd_direct_calls_only = switch_true(val);
+ }
+ }
+
+ if (call_fwd_direct_calls_only) {
+ call_fwd_is_valid = SWITCH_FALSE;
+ if (ctx ) {
+ cJSON *json_flags = cJSON_GetObjectItem(ctx, "Flags");
+ if (json_flags && json_flags->type == cJSON_Array) {
+ cJSON *item;
+ cJSON_ArrayForEach(item, json_flags) {
+ if (!strcmp(item->valuestring, "direct_call")) {
+ call_fwd_is_valid = SWITCH_TRUE;
+ break;
+ }
+ }
+ if (!call_fwd_is_valid) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call fwd requires direct_call and it was not found\n");
+ }
+ }
+ }
+ }
+
+ if (!call_fwd_is_valid) {
+ dest = strdup(endpoint_dial);
+ } else if (call_fwd_is_failover) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "setting failover => %s\n", callforward_dial);
+ dest = strdup(endpoint_dial);
+ failover_dial = callforward_dial;
+ } else if (call_fwd_is_substitute) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "setting call fwd substitute => %s\n", callforward_dial);
+ dest = strdup(callforward_dial);
+ } else {
+ dest = switch_mprintf("%s%s%s", endpoint_dial ? endpoint_dial : "", (endpoint_dial ? endpoint_separator ? endpoint_separator : "," : ""), callforward_dial);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "setting call fwd append => %s => %s\n", callforward_dial, dest);
+ }
+ } else {
+ dest = strdup(endpoint_dial);
+ }
+
dialed_user = (char *)switch_xml_attr(x_user, "id");
if (var_event) {
if (!dest) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No dial-string available, please check your user directory.\n");
cause = SWITCH_CAUSE_MANDATORY_IE_MISSING;
- } else {
- const char *varval;
- char *d_dest = NULL;
- switch_channel_t *channel;
- switch_originate_flag_t myflags = SOF_NONE;
- char *cid_name_override = NULL;
- char *cid_num_override = NULL;
- switch_event_t *event = NULL;
+ goto done;
+ }
- if (var_event) {
- cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name");
- cid_num_override = switch_event_get_header(var_event, "origination_caller_id_number");
+ if (var_event) {
+ cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name");
+ cid_num_override = switch_event_get_header(var_event, "origination_caller_id_number");
+ }
+
+ if(session) {
+ a_session = session;
+ } else if(var_event) {
+ const char* uuid_e_session = switch_event_get_header(var_event, "ent_originate_aleg_uuid");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHECKING ORIGINATE-UUID : %s\n", uuid_e_session);
+ if (uuid_e_session && (e_session = switch_core_session_force_locate(uuid_e_session)) != NULL) {
+ a_session = e_session;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FOUND ORIGINATE-UUID : %s\n", uuid_e_session);
}
+ }
- if(session) {
- a_session = session;
- } else if(var_event) {
- const char* uuid_e_session = switch_event_get_header(var_event, "ent_originate_aleg_uuid");
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHECKING ORIGINATE-UUID : %s\n", uuid_e_session);
- if (uuid_e_session && (e_session = switch_core_session_force_locate(uuid_e_session)) != NULL) {
- a_session = e_session;
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FOUND ORIGINATE-UUID : %s\n", uuid_e_session);
- }
+ if (a_session) {
+ switch_event_create(&event, SWITCH_EVENT_GENERAL);
+ channel = switch_core_session_get_channel(a_session);
+ if ((varval = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE))
+ || (var_event && (varval = switch_event_get_header(var_event, "leg_timeout")))) {
+ timelimit = atoi(varval);
}
+ switch_channel_event_set_data(channel, event);
+
+ switch_channel_set_variable(channel, "dialed_user", dialed_user);
+ switch_channel_set_variable(channel, "dialed_domain", domain);
- if (a_session) {
- switch_event_create(&event, SWITCH_EVENT_GENERAL);
- channel = switch_core_session_get_channel(a_session);
- if ((varval = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE))
- || (var_event && (varval = switch_event_get_header(var_event, "leg_timeout")))) {
+ } else {
+ if (var_event) {
+ switch_event_dup(&event, var_event);
+ switch_event_del_header(event, "dialed_user");
+ switch_event_del_header(event, "dialed_domain");
+ if ((varval = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) ||
+ (varval = switch_event_get_header(var_event, "leg_timeout"))) {
timelimit = atoi(varval);
}
- switch_channel_event_set_data(channel, event);
- if(var_event) {
- switch_event_merge(event, var_event);
- }
+ } else {
+ switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS);
+ switch_assert(event);
+ }
- switch_channel_set_variable(channel, "dialed_user", dialed_user);
- switch_channel_set_variable(channel, "dialed_domain", domain);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_user", dialed_user);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
+ }
- } else {
- if (var_event) {
- switch_event_dup(&event, var_event);
- switch_event_del_header(event, "dialed_user");
- switch_event_del_header(event, "dialed_domain");
- if ((varval = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) ||
- (varval = switch_event_get_header(var_event, "leg_timeout"))) {
- timelimit = atoi(varval);
- }
- } else {
- switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS);
- switch_assert(event);
- }
+ if ((x_params = switch_xml_child(x_user, "profile-variables"))) {
+ for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
+ const char *pvar = switch_xml_attr_soft(x_param, "name");
+ const char *val = switch_xml_attr(x_param, "value");
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding profile variable to event => %s = %s\n", pvar, val);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, pvar, val);
+ }
+ }
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_user", dialed_user);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
+ if ((x_params = switch_xml_child(x_user, "variables"))) {
+ for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
+ const char *pvar = switch_xml_attr_soft(x_param, "name");
+ const char *val = switch_xml_attr(x_param, "value");
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding variable to event => %s = %s\n", pvar, val);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, pvar, val);
}
+ }
- if ((x_params = switch_xml_child(x_user, "profile-variables"))) {
- for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
- const char *pvar = switch_xml_attr_soft(x_param, "name");
- const char *val = switch_xml_attr(x_param, "value");
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding profile variable to event => %s = %s\n", pvar, val);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, pvar, val);
+ if ((x_params = switch_xml_child(x_user, "params"))) {
+ for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
+ const char *pvar = switch_xml_attr_soft(x_param, "name");
+ const char *val = switch_xml_attr(x_param, "value");
+
+ if (!strncasecmp(pvar, "dial-var-", 9)) {
+ switch_event_del_header(event, pvar + 9);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding dialog var to event => %s = %s\n", pvar + 9, val);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, pvar + 9, val);
}
}
+ }
- if ((x_params = switch_xml_child(x_user, "variables"))) {
- for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
- const char *pvar = switch_xml_attr_soft(x_param, "name");
- const char *val = switch_xml_attr(x_param, "value");
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding variable to event => %s = %s\n", pvar, val);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, pvar, val);
+ // add runtime vars to event for expand
+ if (ctx) {
+ cJSON *item = NULL;
+ char *response = NULL;
+ cJSON_ArrayForEach(item, ctx) {
+ if (item->type == cJSON_String) {
+ response = strdup(item->valuestring);
+ } else {
+ response = cJSON_PrintUnformatted(item);
}
+ kz_switch_event_add_variable_name_printf(event, SWITCH_STACK_BOTTOM, response, "kz_ctx_%s", item->string);
+ switch_safe_free(response);
}
+ }
- if ((x_params = switch_xml_child(x_user, "params"))) {
- for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
- const char *pvar = switch_xml_attr_soft(x_param, "name");
- const char *val = switch_xml_attr(x_param, "value");
+ d_dest = kz_event_expand_headers(event, dest);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "dialing %s => %s\n", dest, d_dest);
- if (!strncasecmp(pvar, "dial-var-", 9)) {
- switch_event_del_header(event, pvar + 9);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding dialog var to event => %s = %s\n", pvar + 9, val);
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, pvar + 9, val);
- }
- }
- }
+ if(failover_dial) {
+ b_failover_dial = kz_event_expand_headers(event, failover_dial);
+ }
- d_dest = kz_event_expand_headers(event, dest);
+ if (var_event) {
+ kz_expand_headers(event, var_event);
+ }
- if (var_event) {
- kz_expand_headers(event, var_event);
- }
+ switch_event_destroy(&event);
- switch_event_destroy(&event);
+ if ((flags & SOF_NO_LIMITS)) {
+ myflags |= SOF_NO_LIMITS;
+ }
- if ((flags & SOF_NO_LIMITS)) {
- myflags |= SOF_NO_LIMITS;
- }
+ if ((flags & SOF_FORKED_DIAL)) {
+ myflags |= SOF_NOBLOCK;
+ }
- if ((flags & SOF_FORKED_DIAL)) {
- myflags |= SOF_NOBLOCK;
+ if ( a_session ) {
+ if(var_event) {
+ kz_tweaks_variables_to_event(a_session, var_event);
}
+ }
- if ( a_session ) {
- if(var_event) {
- kz_tweaks_variables_to_event(a_session, var_event);
- }
- }
+ if(e_session) {
+ switch_core_session_rwunlock(e_session);
+ }
- if(e_session) {
- switch_core_session_rwunlock(e_session);
- }
+ switch_snprintf(stupid, sizeof(stupid), "kz/%s", dialed_user);
+ if (switch_stristr(stupid, d_dest)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Waddya Daft? You almost called '%s' in an infinate loop!\n", stupid);
+ cause = SWITCH_CAUSE_INVALID_IE_CONTENTS;
+ goto done;
+ }
- switch_snprintf(stupid, sizeof(stupid), "kz/%s", dialed_user);
- if (switch_stristr(stupid, d_dest)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Waddya Daft? You almost called '%s' in an infinate loop!\n", stupid);
- cause = SWITCH_CAUSE_INVALID_IE_CONTENTS;
- } else if (switch_ivr_originate(session, new_session, &cause, d_dest, timelimit, NULL,
- cid_name_override, cid_num_override, outbound_profile, var_event, myflags,
- cancel_cause, NULL) == SWITCH_STATUS_SUCCESS) {
- const char *context;
- switch_caller_profile_t *cp;
-
- if (var_event) {
- switch_event_del_header(var_event, "origination_uuid");
- }
+ status = switch_ivr_originate(session, new_session, &cause, d_dest, timelimit, NULL,
+ cid_name_override, cid_num_override, outbound_profile, var_event, myflags,
+ cancel_cause, NULL);
- new_channel = switch_core_session_get_channel(*new_session);
+ if (status != SWITCH_STATUS_SUCCESS && b_failover_dial) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "trying failover => %s\n", failover_dial);
+ status = switch_ivr_originate(session, new_session, &cause, b_failover_dial, timelimit, NULL,
+ cid_name_override, cid_num_override, outbound_profile, var_event, myflags,
+ cancel_cause, NULL);
+ }
- if ((context = switch_channel_get_variable(new_channel, "user_context"))) {
- if ((cp = switch_channel_get_caller_profile(new_channel))) {
- cp->context = switch_core_strdup(cp->pool, context);
- }
- }
+ if (status == SWITCH_STATUS_SUCCESS) {
+ const char *context;
+ switch_caller_profile_t *cp;
- /*
- if ((x_params = switch_xml_child(x_user, "variables"))) {
- for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
- const char *pvar = switch_xml_attr(x_param, "name");
- const char *val = switch_xml_attr(x_param, "value");
- switch_channel_set_variable(new_channel, pvar, val);
- }
- }
- */
-
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "CHECKING CALLER-ID\n");
- if ((x_params = switch_xml_child(x_user, "profile-variables"))) {
- switch_caller_profile_t *cp = NULL;
- const char* val = NULL;
- for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
- const char *pvar = switch_xml_attr(x_param, "name");
- const char *val = switch_xml_attr(x_param, "value");
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "setting profile var %s = %s\n", pvar, val);
- switch_channel_set_profile_var(new_channel, pvar, val);
- }
- cp = switch_channel_get_caller_profile(new_channel);
- if((val=switch_caller_get_field_by_name(cp, "Endpoint-Caller-ID-Name"))) {
- cp->callee_id_name = val;
- cp->orig_caller_id_name = val;
- }
- if((val=switch_caller_get_field_by_name(cp, "Endpoint-Caller-ID-Number"))) {
- cp->callee_id_number = val;
- cp->orig_caller_id_number = val;
- }
+ if (var_event) {
+ switch_event_del_header(var_event, "origination_uuid");
+ }
+
+ new_channel = switch_core_session_get_channel(*new_session);
+
+ if ((context = switch_channel_get_variable(new_channel, "user_context"))) {
+ if ((cp = switch_channel_get_caller_profile(new_channel))) {
+ cp->context = switch_core_strdup(cp->pool, context);
}
- switch_core_session_rwunlock(*new_session);
}
- if (d_dest != dest) {
- switch_safe_free(d_dest);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "CHECKING CALLER-ID\n");
+ if ((x_params = switch_xml_child(x_user, "profile-variables"))) {
+ switch_caller_profile_t *cp = NULL;
+ const char* val = NULL;
+ for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
+ const char *pvar = switch_xml_attr(x_param, "name");
+ const char *val = switch_xml_attr(x_param, "value");
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "setting profile var %s = %s\n", pvar, val);
+ switch_channel_set_profile_var(new_channel, pvar, val);
+ }
+ cp = switch_channel_get_caller_profile(new_channel);
+ if((val=switch_caller_get_field_by_name(cp, "Endpoint-Caller-ID-Name"))) {
+ cp->callee_id_name = val;
+ cp->orig_caller_id_name = val;
+ }
+ if((val=switch_caller_get_field_by_name(cp, "Endpoint-Caller-ID-Number"))) {
+ cp->callee_id_number = val;
+ cp->orig_caller_id_number = val;
+ }
}
+ switch_core_session_rwunlock(*new_session);
}
done:
+ if (d_dest && d_dest != dest) {
+ switch_safe_free(d_dest);
+ }
+
+ if(b_failover_dial && b_failover_dial != failover_dial) {
+ switch_safe_free(b_failover_dial);
+ }
+
+ switch_safe_free(dest);
+
+ if (ctx) {
+ cJSON_Delete(ctx);
+ }
+
if (x_user) {
switch_xml_free(x_user);
}