switch_status_t conference_loop_dmachine_dispatcher(switch_ivr_dmachine_match_t *match) { key_binding_t *binding = match->user_data; switch_channel_t *channel; if (!binding) return SWITCH_STATUS_FALSE; channel = switch_core_session_get_channel(binding->member->session); switch_channel_set_variable(channel, "conference_last_matching_digits", match->match_digits); if (binding->action.data) { binding->action.expanded_data = switch_channel_expand_variables(channel, binding->action.data); } binding->handler(binding->member, &binding->action); if (binding->action.expanded_data != binding->action.data) { free(binding->action.expanded_data); binding->action.expanded_data = NULL; } conference_utils_member_set_flag_locked(binding->member, MFLAG_FLUSH_BUFFER); return SWITCH_STATUS_SUCCESS; }
static switch_status_t limit_state_handler(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_channel_state_t state = switch_channel_get_state(channel); const char *vval = switch_channel_get_variable(channel, LIMIT_IGNORE_TRANSFER_VARIABLE); const char *backendlist = switch_channel_get_variable(channel, LIMIT_BACKEND_VARIABLE); if (zstr(backendlist)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unset limit backendlist!\n"); return SWITCH_STATUS_SUCCESS; } if (state >= CS_HANGUP || (state == CS_ROUTING && !switch_true(vval))) { int argc = 0; char *argv[6] = { 0 }; char *mydata = strdup(backendlist); int x; argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0]))); for (x = 0; x < argc; x++) { switch_limit_release(argv[x], session, NULL, NULL); } switch_core_event_hook_remove_state_change(session, limit_state_handler); /* Remove limit_backend variable so we register another hook if limit is called again */ switch_channel_set_variable(channel, LIMIT_BACKEND_VARIABLE, NULL); free(mydata); } return SWITCH_STATUS_SUCCESS; }
static switch_status_t process_event(switch_event_t *event) { switch_core_session_t *session = NULL; switch_channel_t *channel; char *username[3] = { 0 }; char *domain[3] = { 0 }; char key[512]; char *uuid = NULL, *my_uuid = NULL; int i; switch_thread_rwlock_rdlock(globals.spy_hash_lock); if (!globals.spy_count) { goto done; } username[0] = switch_event_get_header(event, "Caller-Username"); domain[0] = switch_event_get_header(event, "variable_domain_name"); domain[1] = switch_event_get_header(event, "variable_dialed_domain"); username[1] = switch_event_get_header(event, "variable_dialed_user"); username[2] = switch_event_get_header(event, "variable_user_name"); domain[2] = switch_event_get_header(event, "variable_domain_name"); for (i = 0; i < 3; i++) { if (username[i] && domain[i]) { switch_snprintf(key, sizeof(key), "%[email protected]%s", username[i], domain[i]); if ((uuid = switch_core_hash_find(globals.spy_hash, key))) { break; } } } done: switch_thread_rwlock_unlock(globals.spy_hash_lock); if (!uuid) { return SWITCH_STATUS_FALSE; } session = switch_core_session_locate(uuid); channel = switch_core_session_get_channel(session); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key); my_uuid = switch_event_get_header(event, "Unique-ID"); switch_channel_set_variable(channel, "spy_uuid", my_uuid); switch_channel_set_state(channel, CS_EXCHANGE_MEDIA); switch_channel_set_flag(channel, CF_BREAK); switch_core_session_rwunlock(session); return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_transfer_recordings(switch_core_session_t *orig_session, switch_core_session_t *new_session) { switch_media_bug_t *bp; char *list[100] = { 0 }; int stop_times[100] = { 0 }; int i = 0, x = 0; if (orig_session->bugs) { switch_channel_t *new_channel = switch_core_session_get_channel(new_session); switch_channel_t *orig_channel = switch_core_session_get_channel(orig_session); const char *save_append = switch_channel_get_variable(new_channel, "record_append"); const char *save_stereo = switch_channel_get_variable(new_channel, "record_stereo"); const char *orig_stereo = switch_channel_get_variable(orig_channel, "record_stereo"); const char *new_stereo = orig_stereo; switch_thread_rwlock_wrlock(orig_session->bug_rwlock); switch_channel_set_variable(new_channel, "RECORD_MIN_SEC", "0"); switch_channel_set_variable(new_channel, "record_append", "true"); switch_channel_set_variable(new_channel, "record_stereo", new_stereo); for (bp = orig_session->bugs; bp; bp = bp->next) { if (!strcmp(bp->function, "session_record")) { list[x] = switch_core_session_strdup(new_session, bp->target); if (bp->stop_time > 0) { stop_times[x] = (int)(bp->stop_time - switch_epoch_time_now(NULL)); } x++; } } switch_thread_rwlock_unlock(orig_session->bug_rwlock); for(i = 0; i < x; i++) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(orig_session), SWITCH_LOG_DEBUG, "Transfering %s from %s to %s\n", list[i], switch_core_session_get_name(orig_session), switch_core_session_get_name(new_session)); switch_ivr_stop_record_session(orig_session, list[i]); switch_ivr_record_session(new_session, list[i], stop_times[i], NULL); } switch_channel_set_variable(new_channel, "record_append", save_append); switch_channel_set_variable(new_channel, "record_stereo", save_stereo); } return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; }
void eventpipe_events_on_conference(switch_core_session_t *session, switch_event_t *event) { char args[8192]; char record_args[8192]; const char *action = switch_str_nil(switch_event_get_header(event, "action")); const char *member_id = switch_str_nil(switch_event_get_header(event, "member-id")); const char *conf_room = switch_str_nil(switch_event_get_header(event, "conference-name")); const char *calluuid = switch_core_session_get_uuid(session); switch_channel_t *channel = switch_core_session_get_channel(session); if (!channel) { return; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Event-Name: %s, Event-Subclass: %s, Conference-Name: %s, Action: %s, Member-ID: %s, Unique-ID: %s\n", switch_str_nil(switch_event_get_header(event, "event-name")), switch_str_nil(switch_event_get_header(event, "event-subclass")), conf_room, action, member_id, calluuid); if (!strcmp(action, "add-member")) { const char *enter_sound = switch_str_nil(switch_channel_get_variable(channel, "eventpipe_conference_enter_sound")); const char *record_file = switch_str_nil(switch_channel_get_variable(channel, "eventpipe_conference_record_file")); switch_channel_set_variable(channel, "eventpipe_conference_member_id", member_id); switch_channel_set_variable(channel, "eventpipe_conference_room", conf_room); if (!zstr(enter_sound)) { switch_snprintf(args, sizeof(args), "%s play %s async", conf_room, enter_sound); eventpipe_execute_api(session, "conference", args); } if (!zstr(record_file)) { switch_snprintf(record_args, sizeof(record_args), "%s record %s", conf_room, record_file); eventpipe_execute_api(session, "conference", record_args); } } else if (!strcmp(action, "del-member")) { const char *exit_sound = switch_str_nil(switch_channel_get_variable(channel, "eventpipe_conference_exit_sound")); switch_channel_set_variable(channel, "eventpipe_conference_member_id", ""); switch_channel_set_variable(channel, "eventpipe_conference_room", ""); switch_channel_set_variable(channel, "eventpipe_conference_record_file", ""); if (!zstr(exit_sound)) { switch_snprintf(args, sizeof(args), "conference %s play %s async", conf_room, exit_sound); eventpipe_execute_api(session, "conference", args); } } }
static switch_bool_t amd_handle_silence_frame(amd_vad_t *vad, const switch_frame_t *f) { vad->silence_duration += vad->frame_ms; if (vad->silence_duration >= globals.between_words_silence) { if (vad->state != VAD_STATE_IN_SILENCE) { switch_log_printf( SWITCH_CHANNEL_SESSION_LOG(vad->session), SWITCH_LOG_DEBUG, "AMD: Changed state to VAD_STATE_IN_SILENCE\n"); } vad->state = VAD_STATE_IN_SILENCE; vad->voice_duration = 0; } if (vad->in_initial_silence && vad->silence_duration >= globals.initial_silence) { switch_log_printf( SWITCH_CHANNEL_SESSION_LOG(vad->session), SWITCH_LOG_DEBUG, "AMD: MACHINE (silence_duration: %d, initial_silence: %d)\n", vad->silence_duration, globals.initial_silence); switch_channel_set_variable(vad->channel, "amd_result", "MACHINE"); switch_channel_set_variable(vad->channel, "amd_cause", "INITIALSILENCE"); return SWITCH_TRUE; } if (vad->silence_duration >= globals.after_greeting_silence && vad->in_greeting) { switch_log_printf( SWITCH_CHANNEL_SESSION_LOG(vad->session), SWITCH_LOG_DEBUG, "AMD: HUMAN (silence_duration: %d, after_greeting_silence: %d)\n", vad->silence_duration, globals.after_greeting_silence); switch_channel_set_variable(vad->channel, "amd_result", "HUMAN"); switch_channel_set_variable(vad->channel, "amd_cause", "HUMAN"); return SWITCH_TRUE; } return SWITCH_FALSE; }
static void check_presence(switch_core_session_t *session) { switch_channel_state_t state = switch_channel_get_running_state(session->channel); if (state == CS_ROUTING || state == CS_HANGUP) { if (switch_channel_get_cause(session->channel) == SWITCH_CAUSE_LOSE_RACE) { switch_channel_presence(session->channel, "unknown", "cancelled", NULL); switch_channel_set_variable(session->channel, "presence_call_info", NULL); } else { switch_channel_presence(session->channel, "unknown", switch_channel_state_name(state), NULL); } } }
SWITCH_DECLARE(switch_status_t) switch_core_session_set_video_read_codec(switch_core_session_t *session, switch_codec_t *codec) { switch_event_t *event; switch_channel_t *channel = switch_core_session_get_channel(session); char tmp[30]; switch_status_t status = SWITCH_STATUS_SUCCESS; if (!codec || !codec->implementation || !switch_core_codec_ready(codec)) { if (session->video_read_codec) { session->video_read_codec = NULL; status = SWITCH_STATUS_SUCCESS; goto end; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot set NULL codec!\n"); status = SWITCH_STATUS_FALSE; goto end; } if (switch_event_create(&event, SWITCH_EVENT_CODEC) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(session->channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-video-read-codec-name", codec->implementation->iananame); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-video-read-codec-rate", "%d", codec->implementation->actual_samples_per_second); switch_event_fire(&event); } switch_channel_set_variable(channel, "video_read_codec", codec->implementation->iananame); switch_snprintf(tmp, sizeof(tmp), "%d", codec->implementation->actual_samples_per_second); switch_channel_set_variable(channel, "video_read_rate", tmp); session->video_read_codec = codec; if (codec->implementation) { session->video_read_impl = *codec->implementation; } else { memset(&session->video_read_impl, 0, sizeof(session->video_read_impl)); } end: return status; }
static void switch_core_standard_on_reset(switch_core_session_t *session) { switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session)); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard RESET\n", switch_channel_get_name(session->channel)); if (switch_channel_test_flag(session->channel, CF_RECOVERING_BRIDGE)) { switch_core_session_t *other_session = NULL; const char *uuid = switch_core_session_get_uuid(session); if (switch_channel_test_flag(session->channel, CF_BRIDGE_ORIGINATOR)) { const char *other_uuid = switch_channel_get_partner_uuid(session->channel); int x = 0; if (other_uuid) { for (x = 0; other_session == NULL && x < 20; x++) { if (!switch_channel_up(session->channel)) { break; } other_session = switch_core_session_locate(other_uuid); switch_yield(100000); } } if (other_session) { switch_channel_t *other_channel = switch_core_session_get_channel(other_session); switch_channel_clear_flag(session->channel, CF_BRIDGE_ORIGINATOR); switch_channel_wait_for_state_timeout(other_channel, CS_RESET, 5000); switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 2000, NULL); if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) && switch_channel_test_flag(other_channel, CF_PROXY_MODE)) { switch_ivr_signal_bridge(session, other_session); } else { switch_ivr_uuid_bridge(uuid, other_uuid); } switch_core_session_rwunlock(other_session); } } switch_channel_clear_flag(session->channel, CF_RECOVERING_BRIDGE); } }
static void save_extra_headers(switch_event_t *extra_headers, switch_channel_t *channel) { switch_event_header_t *ei = NULL; for (ei = switch_channel_variable_first(channel); ei; ei = ei->next) { const char *name = ei->name; char *value = ei->value; if (!strncasecmp(name, SIP_OREKA_HEADER_PREFIX, SIP_OREKA_HEADER_PREFIX_LEN)) { switch_event_add_header_string(extra_headers, SWITCH_STACK_BOTTOM, name, value); } } switch_channel_variable_last(channel); /* Remove the custom header variables that were saved */ for (ei = extra_headers->headers; ei; ei = ei->next) { char *varname = ei->name; switch_channel_set_variable(channel, varname, NULL); } }
SWITCH_DECLARE(switch_status_t) switch_limit_incr(const char *backend, switch_core_session_t *session, const char *realm, const char *resource, const int max, const int interval) { switch_limit_interface_t *limit = NULL; switch_channel_t *channel = NULL; int status = SWITCH_STATUS_SUCCESS; if (session) { channel = switch_core_session_get_channel(session); } /* locate impl, call appropriate func */ if (!(limit = get_backend(backend))) { switch_limit_log(session, SWITCH_LOG_ERROR, "Limit subsystem %s not found!\n", backend); switch_goto_status(SWITCH_STATUS_GENERR, end); } switch_limit_log(session, SWITCH_LOG_INFO, "incr called: %s_%s max:%d, interval:%d\n", realm, resource, max, interval); if ((status = limit->incr(session, realm, resource, max, interval)) == SWITCH_STATUS_SUCCESS) { if (session) { /* race condition? what if another leg is doing the same thing? */ const char *existing = switch_channel_get_variable(channel, LIMIT_BACKEND_VARIABLE); if (existing) { if (!strstr(existing, backend)) { switch_channel_set_variable_printf(channel, LIMIT_BACKEND_VARIABLE, "%s,%s", existing, backend); } } else { switch_channel_set_variable(channel, LIMIT_BACKEND_VARIABLE, backend); switch_core_event_hook_add_state_change(session, limit_state_handler); } } } release_backend(limit); end: return status; }
static switch_status_t channel_on_hangup(switch_core_session_t *session) { switch_channel_t *channel = NULL; loopback_private_t *tech_pvt = NULL; channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); switch_channel_set_variable(channel, "is_loopback", "1"); tech_pvt = switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel)); switch_clear_flag_locked(tech_pvt, TFLAG_LINKED); switch_mutex_lock(tech_pvt->mutex); if (tech_pvt->other_tech_pvt) { switch_clear_flag_locked(tech_pvt->other_tech_pvt, TFLAG_LINKED); if (tech_pvt->other_tech_pvt->session && tech_pvt->other_tech_pvt->session != tech_pvt->other_session) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "OTHER SESSION MISMATCH????\n"); tech_pvt->other_session = tech_pvt->other_tech_pvt->session; } tech_pvt->other_tech_pvt = NULL; } if (tech_pvt->other_session) { switch_channel_hangup(tech_pvt->other_channel, switch_channel_get_cause(channel)); switch_core_session_rwunlock(tech_pvt->other_session); tech_pvt->other_channel = NULL; tech_pvt->other_session = NULL; } switch_mutex_unlock(tech_pvt->mutex); return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(switch_status_t) switch_core_session_set_read_codec(switch_core_session_t *session, switch_codec_t *codec) { switch_event_t *event; switch_channel_t *channel = switch_core_session_get_channel(session); char tmp[30]; switch_status_t status = SWITCH_STATUS_SUCCESS; switch_mutex_lock(session->codec_read_mutex); if (codec && (!codec->implementation || !switch_core_codec_ready(codec))) { codec = NULL; } if (codec) { if (!session->real_read_codec) { session->read_codec = session->real_read_codec = codec; if (codec->implementation) { session->read_impl = *codec->implementation; session->real_read_impl = *codec->implementation; } else { memset(&session->read_impl, 0, sizeof(session->read_impl)); } } else { if (codec == session->read_codec) { goto end; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Push codec %s:%d\n", switch_channel_get_name(session->channel), codec->implementation->iananame, codec->implementation->ianacode); codec->next = session->read_codec; session->read_codec = codec; if (codec->implementation) { session->read_impl = *codec->implementation; } else { memset(&session->read_impl, 0, sizeof(session->read_impl)); } } } else { if (session->read_codec == session->real_read_codec) { goto end; } if (session->read_codec->next) { switch_codec_t *old = session->read_codec; session->read_codec = session->read_codec->next; if (session->read_codec->implementation) { session->read_impl = *session->read_codec->implementation; } else { memset(&session->read_impl, 0, sizeof(session->read_impl)); } old->next = NULL; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Restore previous codec %s:%d.\n", switch_channel_get_name(session->channel), session->read_impl.iananame ? session->read_impl.iananame : "N/A", session->read_impl.ianacode); } else if (session->real_read_codec) { session->read_codec = session->real_read_codec; if (session->real_read_codec->implementation) { session->read_impl = *session->real_read_codec->implementation; } else { memset(&session->read_impl, 0, sizeof(session->read_impl)); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Restore original codec.\n"); } else { status = SWITCH_STATUS_FALSE; goto end; } } if (!session->read_codec) { status = SWITCH_STATUS_FALSE; goto end; } if (session->read_codec && session->read_impl.decoded_bytes_per_packet) { if (switch_event_create(&event, SWITCH_EVENT_CODEC) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(session->channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-read-codec-name", session->read_impl.iananame); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-rate", "%d", session->read_impl.actual_samples_per_second); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-bit-rate", "%d", session->read_impl.bits_per_second); if (session->read_impl.actual_samples_per_second != session->read_impl.samples_per_second) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-reported-read-codec-rate", "%d", session->read_impl.samples_per_second); } switch_event_fire(&event); } switch_channel_set_variable(channel, "read_codec", session->read_impl.iananame); switch_snprintf(tmp, sizeof(tmp), "%d", session->read_impl.actual_samples_per_second); switch_channel_set_variable(channel, "read_rate", tmp); session->raw_read_frame.codec = session->read_codec; session->raw_write_frame.codec = session->read_codec; session->enc_read_frame.codec = session->read_codec; session->enc_write_frame.codec = session->read_codec; } end: if (session->read_codec) { switch_channel_set_flag(channel, CF_MEDIA_SET); } switch_mutex_unlock(session->codec_read_mutex); return status; }
SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf_string(switch_core_session_t *session, const char *dtmf_string) { char *p; switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0) }; int sent = 0, dur; char *string; int i, argc; char *argv[256]; int dur_total = 0; switch_assert(session != NULL); if (switch_channel_down(session->channel)) { return SWITCH_STATUS_FALSE; } if (zstr(dtmf_string)) { return SWITCH_STATUS_FALSE; } if (strlen(dtmf_string) > 99) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Attempt to send very large dtmf string ignored!\n"); return SWITCH_STATUS_FALSE; } string = switch_core_session_strdup(session, dtmf_string); argc = switch_separate_string(string, '+', argv, (sizeof(argv) / sizeof(argv[0]))); if (argc) { switch_channel_pre_answer(session->channel); } for (i = 0; i < argc; i++) { dtmf.duration = switch_core_default_dtmf_duration(0); dur = switch_core_default_dtmf_duration(0) / 8; if ((p = strchr(argv[i], '@'))) { *p++ = '\0'; if ((dur = atoi(p)) > 50) { dtmf.duration = dur * 8; } } if (dtmf.duration > switch_core_max_dtmf_duration(0)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s EXCESSIVE DTMF DIGIT [%c] LEN [%d]\n", switch_channel_get_name(session->channel), dtmf.digit, dtmf.duration); dtmf.duration = switch_core_max_dtmf_duration(0); } else if (dtmf.duration < switch_core_min_dtmf_duration(0)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s SHORT DTMF DIGIT [%c] LEN [%d]\n", switch_channel_get_name(session->channel), dtmf.digit, dtmf.duration); dtmf.duration = switch_core_min_dtmf_duration(0); } else if (!dtmf.duration) { dtmf.duration = switch_core_default_dtmf_duration(0); } for (p = argv[i]; p && *p; p++) { if (is_dtmf(*p)) { dtmf.digit = *p; if (switch_core_session_send_dtmf(session, &dtmf) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s send dtmf\ndigit=%c ms=%u samples=%u\n", switch_channel_get_name(session->channel), dtmf.digit, dur, dtmf.duration); sent++; dur_total += dtmf.duration + 2000; /* account for 250ms pause */ } } } if (dur_total) { char tmp[32] = ""; switch_snprintf(tmp, sizeof(tmp), "%d", dur_total / 8); switch_channel_set_variable(session->channel, "last_dtmf_duration", tmp); } } return sent ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; }
/** * Start recording call * @param session the session to record * @param record the record component */ static int start_call_record(switch_core_session_t *session, struct rayo_component *component) { struct record_component *record_component = RECORD_COMPONENT(component); switch_channel_t *channel = switch_core_session_get_channel(session); int max_duration_sec = 0; switch_channel_set_variable(channel, "RECORD_HANGUP_ON_ERROR", "false"); switch_channel_set_variable(channel, "RECORD_TOGGLE_ON_REPEAT", ""); switch_channel_set_variable(channel, "RECORD_CHECK_BRIDGE", ""); switch_channel_set_variable(channel, "RECORD_MIN_SEC", "0"); switch_channel_set_variable(channel, "RECORD_STEREO", ""); switch_channel_set_variable(channel, "RECORD_READ_ONLY", ""); switch_channel_set_variable(channel, "RECORD_WRITE_ONLY", ""); switch_channel_set_variable(channel, "RECORD_APPEND", ""); switch_channel_set_variable(channel, "RECORD_WRITE_OVER", "true"); switch_channel_set_variable(channel, "RECORD_ANSWER_REQ", ""); switch_channel_set_variable(channel, "RECORD_SILENCE_THRESHOLD", "200"); if (record_component->initial_timeout > 0) { switch_channel_set_variable_printf(channel, "RECORD_INITIAL_TIMEOUT_MS", "%i", record_component->initial_timeout); } else { switch_channel_set_variable(channel, "RECORD_INITIAL_TIMEOUT_MS", ""); } if (record_component->final_timeout > 0) { switch_channel_set_variable_printf(channel, "RECORD_FINAL_TIMEOUT_MS", "%i", record_component->final_timeout); } else { switch_channel_set_variable(channel, "RECORD_FINAL_TIMEOUT_MS", ""); } /* allow dialplan override for these variables */ //switch_channel_set_variable(channel, "RECORD_PRE_BUFFER_FRAMES", ""); //switch_channel_set_variable(channel, "record_sample_rate", ""); //switch_channel_set_variable(channel, "enable_file_write_buffering", ""); /* max duration attribute is in milliseconds- convert to seconds */ if (record_component->max_duration > 0) { max_duration_sec = ceil((double)(record_component->max_duration - record_component->duration_ms) / 1000.0); } if (!strcmp(record_component->direction, "duplex")) { if (!record_component->mix) { /* STEREO */ switch_channel_set_variable(channel, "RECORD_STEREO", "true"); } /* else MONO (default) */ } else if (!strcmp(record_component->direction, "send")) { /* record audio sent from the caller */ switch_channel_set_variable(channel, "RECORD_READ_ONLY", "true"); } else if (!strcmp(record_component->direction, "recv")) { /* record audio received by the caller */ switch_channel_set_variable(channel, "RECORD_WRITE_ONLY", "true"); }; if (record_component->start_beep) { switch_ivr_displace_session(session, RECORD_BEEP, 0, ""); record_component->start_time = switch_micro_time_now(); } if (switch_ivr_record_session(session, (char *)RAYO_ID(component), max_duration_sec, NULL) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Recording started: file = %s\n", RAYO_ID(component)); return 1; } return 0; }
SWITCH_DECLARE(void) switch_core_session_hangup_state(switch_core_session_t *session, switch_bool_t force) { switch_call_cause_t cause = switch_channel_get_cause(session->channel); switch_call_cause_t cause_q850 = switch_channel_get_cause_q850(session->channel); int proceed = 1; int global_proceed = 1; int do_extra_handlers = 1; int silly = 0; int index = 0; switch_channel_state_t state = switch_channel_get_state(session->channel), midstate = state; const switch_endpoint_interface_t *endpoint_interface; const switch_state_handler_table_t *driver_state_handler = NULL; const switch_state_handler_table_t *application_state_handler = NULL; const char *hook_var; int use_session = 0; if (!force) { if (!switch_channel_test_flag(session->channel, CF_EARLY_HANGUP) && !switch_test_flag((&runtime), SCF_EARLY_HANGUP)) { return; } if (switch_thread_self() != session->thread_id) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "%s thread mismatch skipping state handler.\n", switch_channel_get_name(session->channel)); return; } } if (switch_test_flag(session, SSF_HANGUP)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "%s handler already called, skipping state handler.\n", switch_channel_get_name(session->channel)); return; } endpoint_interface = session->endpoint_interface; switch_assert(endpoint_interface != NULL); driver_state_handler = endpoint_interface->state_handler; switch_assert(driver_state_handler != NULL); switch_channel_set_hangup_time(session->channel); switch_core_media_bug_remove_all(session); switch_channel_stop_broadcast(session->channel); switch_channel_set_variable(session->channel, "hangup_cause", switch_channel_cause2str(cause)); switch_channel_set_variable_printf(session->channel, "hangup_cause_q850", "%d", cause_q850); //switch_channel_presence(session->channel, "unknown", switch_channel_cause2str(cause), NULL); switch_channel_set_timestamps(session->channel); STATE_MACRO(hangup, "HANGUP"); switch_core_media_set_stats(session); if ((hook_var = switch_channel_get_variable(session->channel, SWITCH_API_HANGUP_HOOK_VARIABLE))) { if (switch_true(switch_channel_get_variable(session->channel, SWITCH_SESSION_IN_HANGUP_HOOK_VARIABLE))) { use_session = 1; } api_hook(session, hook_var, use_session); } switch_channel_set_callstate(session->channel, CCS_HANGUP); switch_set_flag(session, SSF_HANGUP); }
static void switch_core_standard_on_execute(switch_core_session_t *session) { switch_caller_extension_t *extension; const char *uuid; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard EXECUTE\n", switch_channel_get_name(session->channel)); switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session)); if (switch_channel_get_variable(session->channel, "recovered") && !switch_channel_test_flag(session->channel, CF_RECOVERED)) { switch_channel_set_flag(session->channel, CF_RECOVERED); } top: switch_channel_clear_flag(session->channel, CF_RESET); if ((extension = switch_channel_get_caller_extension(session->channel)) == 0) { switch_channel_hangup(session->channel, SWITCH_CAUSE_NORMAL_CLEARING); return; } while (switch_channel_get_state(session->channel) == CS_EXECUTE && extension->current_application) { switch_caller_application_t *current_application = extension->current_application; extension->current_application = extension->current_application->next; if (switch_core_session_execute_application(session, current_application->application_name, current_application->application_data) != SWITCH_STATUS_SUCCESS) { return; } if (switch_channel_test_flag(session->channel, CF_RESET)) { goto top; } } if (switch_channel_ready(session->channel) && switch_channel_get_state(session->channel) == CS_EXECUTE && switch_channel_test_flag(session->channel, CF_CONFIRM_BLIND_TRANSFER) && (uuid = switch_channel_get_variable(session->channel, "blind_transfer_uuid"))) { switch_core_session_t *other_session; if ((other_session = switch_core_session_locate(uuid))) { switch_core_session_message_t msg = { 0 }; msg.message_id = SWITCH_MESSAGE_INDICATE_BLIND_TRANSFER_RESPONSE; msg.from = __FILE__; msg.numeric_arg = 0; switch_core_session_receive_message(other_session, &msg); switch_core_session_rwunlock(other_session); switch_channel_set_variable(session->channel, "park_timeout", "10:blind_transfer"); switch_channel_set_state(session->channel, CS_PARK); switch_channel_clear_flag(session->channel, CF_CONFIRM_BLIND_TRANSFER); } } if (switch_channel_ready(session->channel) && switch_channel_get_state(session->channel) == CS_EXECUTE) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s has executed the last dialplan instruction, hanging up.\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_NORMAL_CLEARING); } }
static void switch_core_standard_on_reset(switch_core_session_t *session) { switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session)); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard RESET\n", switch_channel_get_name(session->channel)); }
SWITCH_DECLARE(switch_status_t) switch_ivr_menu_execute(switch_core_session_t *session, switch_ivr_menu_t *stack, char *name, void *obj) { int reps = 0, errs = 0, timeouts = 0, match = 0, running = 1; char *greeting_sound = NULL, *aptr = NULL; char arg[512]; switch_ivr_action_t todo = SWITCH_IVR_ACTION_DIE; switch_ivr_menu_action_t *ap; switch_ivr_menu_t *menu; switch_channel_t *channel; switch_status_t status = SWITCH_STATUS_SUCCESS; if (++stack->stack_count > 12) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Too many levels of recursion.\n"); switch_goto_status(SWITCH_STATUS_FALSE, end); } if (!session || !stack || zstr(name)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid menu context\n"); switch_goto_status(SWITCH_STATUS_FALSE, end); } channel = switch_core_session_get_channel(session); if (!(menu = switch_ivr_menu_find(stack, name))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Menu!\n"); switch_goto_status(SWITCH_STATUS_FALSE, end); } if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) { switch_channel_set_variable(channel, "tts_engine", menu->tts_engine); switch_channel_set_variable(channel, "tts_voice", menu->tts_voice); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Executing IVR menu %s\n", menu->name); switch_channel_set_variable(channel, "ivr_menu_status", "success"); for (reps = 0; running && status == SWITCH_STATUS_SUCCESS; reps++) { if (!switch_channel_ready(channel)) { break; } if (errs == menu->max_failures) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum failures\n"); switch_channel_set_variable(channel, "ivr_menu_status", "failure"); break; } if (timeouts == menu->max_timeouts) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum timeouts\n"); switch_channel_set_variable(channel, "ivr_menu_status", "timeout"); break; } if (reps > 0 && menu->short_greeting_sound) { greeting_sound = menu->short_greeting_sound; } else { greeting_sound = menu->greeting_sound; } match = 0; aptr = NULL; memset(arg, 0, sizeof(arg)); memset(menu->buf, 0, menu->inlen + 1); if (play_and_collect(session, menu, greeting_sound, menu->inlen) == SWITCH_STATUS_TIMEOUT && *menu->buf == '\0') { timeouts++; continue; } if (*menu->buf != '\0') { for (ap = menu->actions; ap; ap = ap->next) { int ok = 0; char substituted[1024]; char *use_arg = ap->arg; if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) { switch_channel_set_variable(channel, "tts_engine", menu->tts_engine); switch_channel_set_variable(channel, "tts_voice", menu->tts_voice); } if (ap->re) { switch_regex_t *re = NULL; int ovector[30]; if ((ok = switch_regex_perform(menu->buf, ap->bind, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { switch_perform_substitution(re, ok, ap->arg, menu->buf, substituted, sizeof(substituted), ovector); use_arg = substituted; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "action regex [%s] [%s] [%d]\n", menu->buf, ap->bind, ok); switch_regex_safe_free(re); } else { ok = !strcmp(menu->buf, ap->bind); } if (ok) { match++; errs = 0; if (ap->function) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR function on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, use_arg); todo = ap->function(menu, use_arg, arg, sizeof(arg), obj); aptr = arg; } else { todo = ap->ivr_action; aptr = use_arg; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR action on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, aptr); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "switch_ivr_menu_execute todo=[%d]\n", todo); switch (todo) { case SWITCH_IVR_ACTION_DIE: status = SWITCH_STATUS_FALSE; break; case SWITCH_IVR_ACTION_PLAYSOUND: status = switch_ivr_play_file(session, NULL, aptr, NULL); break; case SWITCH_IVR_ACTION_EXECMENU: if (!strcmp(aptr, menu->name)) { status = SWITCH_STATUS_SUCCESS; } else { reps = -1; status = switch_ivr_menu_execute(session, stack, aptr, obj); } break; case SWITCH_IVR_ACTION_EXECAPP: { switch_application_interface_t *application_interface; char *app_name; char *app_arg = NULL; status = SWITCH_STATUS_FALSE; if (!zstr(aptr)) { app_name = switch_core_session_strdup(session, aptr); if ((app_arg = strchr(app_name, ' '))) { *app_arg++ = '\0'; } if ((application_interface = switch_loadable_module_get_application_interface(app_name))) { switch_core_session_exec(session, application_interface, app_arg); UNPROTECT_INTERFACE(application_interface); status = SWITCH_STATUS_SUCCESS; } } } break; case SWITCH_IVR_ACTION_BACK: running = 0; status = SWITCH_STATUS_SUCCESS; break; case SWITCH_IVR_ACTION_TOMAIN: switch_set_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN); status = SWITCH_STATUS_BREAK; break; case SWITCH_IVR_ACTION_NOOP: status = SWITCH_STATUS_SUCCESS; break; default: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid TODO!\n"); break; } } } if (switch_test_flag(menu, SWITCH_IVR_MENU_FLAG_STACK)) { /* top level */ if (switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN)) { /* catch the fallback and recover */ switch_clear_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN); status = SWITCH_STATUS_SUCCESS; running = 1; continue; } } } if (!match) { if (*menu->buf) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' caught invalid input '%s'\n", menu->name, menu->buf); if (menu->invalid_sound) { play_and_collect(session, menu, menu->invalid_sound, 0); } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' no input detected\n", menu->name); } errs++; /* breaks are ok too */ if (SWITCH_STATUS_IS_BREAK(status)) { status = SWITCH_STATUS_SUCCESS; } } } if (stack->stack_count == 1) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "exit-sound '%s'\n", menu->exit_sound); if (!zstr(menu->exit_sound)) { status = play_and_collect(session, menu, menu->exit_sound, 0); } } end: stack->stack_count--; return status; }
static switch_bool_t fsk_detect_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) { switch_fsk_detect_t *pvt = (switch_fsk_detect_t *) user_data; //switch_frame_t *frame = NULL; switch_channel_t *channel = switch_core_session_get_channel(pvt->session); switch (type) { case SWITCH_ABC_TYPE_INIT: { switch_codec_implementation_t read_impl = { 0 }; switch_core_session_get_read_impl(pvt->session, &read_impl); if (fsk_demod_init(&pvt->fsk_data, read_impl.actual_samples_per_second, pvt->fbuf, sizeof(pvt->fbuf))) { return SWITCH_FALSE; } break; } case SWITCH_ABC_TYPE_CLOSE: { fsk_demod_destroy(&pvt->fsk_data); } break; case SWITCH_ABC_TYPE_WRITE_REPLACE: case SWITCH_ABC_TYPE_READ_REPLACE: { switch_frame_t *rframe; if (type == SWITCH_ABC_TYPE_READ_REPLACE) { rframe = switch_core_media_bug_get_read_replace_frame(bug); } else { rframe = switch_core_media_bug_get_write_replace_frame(bug); } if (!pvt->skip && fsk_demod_feed(&pvt->fsk_data, rframe->data, rframe->datalen / 2) != SWITCH_STATUS_SUCCESS) { char str[1024] = ""; size_t type, mlen; char *sp; switch_event_t *event; const char *app_var; int total = 0; switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA); while(fsk_data_parse(&pvt->fsk_data, &type, &sp, &mlen) == SWITCH_STATUS_SUCCESS) { char *varname = NULL, *val, *p; switch_copy_string(str, sp, mlen+1); *(str+mlen) = '\0'; switch_clean_string(str); //printf("TYPE %u LEN %u VAL [%s]\n", (unsigned)type, (unsigned)mlen, str); val = str; switch(type) { case MDMF_DATETIME: varname = "fsk_datetime"; break; case MDMF_PHONE_NAME: varname = "fsk_phone_name"; break; case MDMF_PHONE_NUM: varname = "fsk_phone_num"; break; case MDMF_NAME_VALUE: varname = switch_core_session_sprintf(pvt->session, "fsk_%s", val); if ((p = strchr(varname, ':'))) { *p++ = '\0'; val = p; } break; default: break; } if (varname && val) { total++; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s setting FSK var [%s][%s]\n", switch_channel_get_name(channel), varname, val); switch_channel_set_variable(channel, varname, val); if (event) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, varname, val); } } } if (event) { if (switch_core_session_queue_event(pvt->session, &event) != SWITCH_STATUS_SUCCESS) { switch_event_destroy(&event); } } if (total && (app_var = switch_channel_get_variable(channel, "execute_on_fsk"))) { char *app_arg; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s processing execute_on_fsk [%s]\n", switch_channel_get_name(channel), app_var); if ((app_arg = strchr(app_var, ' '))) { *app_arg++ = '\0'; } switch_core_session_execute_application(pvt->session, app_var, app_arg); } pvt->skip = 10; } memset(rframe->data, 255, rframe->datalen); if (type == SWITCH_ABC_TYPE_READ_REPLACE) { switch_core_media_bug_set_read_replace_frame(bug, rframe); } else { switch_core_media_bug_set_write_replace_frame(bug, rframe); } if (pvt->skip && !--pvt->skip) { return SWITCH_FALSE; } } break; case SWITCH_ABC_TYPE_WRITE: default: break; } return SWITCH_TRUE; }
WSChannel* WSClientParser::CreateCall( switch_core_session_t *session, const char *profileName, const char *profileContext, const char *profileDialplan, const char* ip ) { WSChannel *wsChannel = NULL; switch_memory_pool_t *pool = NULL; switch_channel_t* channel = NULL; switch_caller_profile_t *caller_profile = NULL; char *user = mpUser; char *domain = mpDomain; const char *destNumber = mpDestNumber; const char *context = NULL; const char *dialplan = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::CreateCall( " "this : %p, " "profileName : '%s', " "profileContext : '%s', " "profileDialplan : '%s', " "ip : '%s' " ") \n", this, profileName, profileContext, profileDialplan, ip ); // 参数不能为空 if ( !user || !domain || !destNumber ) { status = SWITCH_STATUS_FALSE; } // 不允许一个连接创建多个会话 if( status == SWITCH_STATUS_SUCCESS && mpChannel ) { status = SWITCH_STATUS_FALSE; } if( status == SWITCH_STATUS_SUCCESS ) { pool = switch_core_session_get_pool(session); channel = switch_core_session_get_channel(session); switch_channel_set_name( channel, switch_core_session_sprintf(session, "ws/%s/%s/%s", profileName, user, destNumber) ); } // if ( status == SWITCH_STATUS_SUCCESS && !zstr(user) && !zstr(domain)) { // // 拨号不做验证 // const char *ivrUser = switch_core_session_sprintf(session, "%[email protected]%s", user, domain); // status = switch_ivr_set_user(session, ivrUser); // } if( status == SWITCH_STATUS_SUCCESS ) { if (!(context = switch_channel_get_variable(channel, "user_context"))) { if (!(context = profileContext)) { context = "public"; } } if (!(dialplan = switch_channel_get_variable(channel, "inbound_dialplan"))) { if (!(dialplan = profileDialplan)) { dialplan = "LUA"; } } // switch_log_printf( // SWITCH_CHANNEL_SESSION_LOG(session), // SWITCH_LOG_NOTICE, // "WSClientParser::CreateCall( " // "context : %s, " // "dialplan : %s " // ") \n", // context, // dialplan // ); // 设置主叫 caller_profile = switch_caller_profile_new( pool, switch_str_nil(user), dialplan, SWITCH_DEFAULT_CLID_NAME, !zstr(user) ? user : SWITCH_DEFAULT_CLID_NUMBER, ip /* net addr */, NULL /* ani */, NULL /* anii */, NULL /* rdnis */, "mod_ws", context, destNumber ); switch_channel_set_caller_profile(channel, caller_profile); switch_core_session_add_stream(session, NULL); switch_channel_set_variable(channel, "caller", user); switch_channel_set_state(channel, CS_INIT); wsChannel = CreateChannel(session); } if( wsChannel ) { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::CreateCall( " "[Success], " "this : %p, " "wsChannel : %p, " "profileName : '%s', " "profileContext : '%s', " "profileDialplan : '%s', " "ip : '%s' " ") \n", this, wsChannel, profileName, profileContext, profileDialplan, ip ); } else { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_ERROR, "WSClientParser::CreateCall( " "[Fail], " "this : %p " ") \n", this, profileName, profileContext, profileDialplan, ip ); } return wsChannel; }
/* State methods they get called when the state changes to the specific state returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it. */ static switch_status_t channel_on_init(switch_core_session_t *session) { switch_channel_t *channel, *b_channel; private_t *tech_pvt = NULL, *b_tech_pvt = NULL; switch_core_session_t *b_session; char name[128]; switch_caller_profile_t *caller_profile; tech_pvt = switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND) && !switch_test_flag(tech_pvt, TFLAG_BLEG)) { if (!(b_session = switch_core_session_request(loopback_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, NULL))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failure.\n"); goto end; } if (switch_core_session_read_lock(b_session) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failure.\n"); switch_core_session_destroy(&b_session); goto end; } switch_core_session_add_stream(b_session, NULL); b_channel = switch_core_session_get_channel(b_session); b_tech_pvt = (private_t *) switch_core_session_alloc(b_session, sizeof(*b_tech_pvt)); switch_snprintf(name, sizeof(name), "loopback/%s-b", tech_pvt->caller_profile->destination_number); switch_channel_set_name(b_channel, name); if (tech_init(b_tech_pvt, b_session, switch_core_session_get_read_codec(session)) != SWITCH_STATUS_SUCCESS) { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); switch_core_session_destroy(&b_session); goto end; } caller_profile = switch_caller_profile_clone(b_session, tech_pvt->caller_profile); caller_profile->source = switch_core_strdup(caller_profile->pool, modname); switch_channel_set_caller_profile(b_channel, caller_profile); b_tech_pvt->caller_profile = caller_profile; switch_channel_set_state(b_channel, CS_INIT); tech_pvt->other_session = b_session; tech_pvt->other_tech_pvt = b_tech_pvt; tech_pvt->other_channel = b_channel; //b_tech_pvt->other_session = session; //b_tech_pvt->other_tech_pvt = tech_pvt; //b_tech_pvt->other_channel = channel; b_tech_pvt->other_uuid = switch_core_session_strdup(b_session, switch_core_session_get_uuid(session)); switch_set_flag_locked(tech_pvt, TFLAG_LINKED); switch_set_flag_locked(b_tech_pvt, TFLAG_LINKED); switch_set_flag_locked(b_tech_pvt, TFLAG_BLEG); switch_channel_set_flag(channel, CF_ACCEPT_CNG); //switch_ivr_transfer_variable(session, tech_pvt->other_session, "process_cdr"); switch_ivr_transfer_variable(session, tech_pvt->other_session, NULL); switch_channel_set_variable(channel, "other_loopback_leg_uuid", switch_channel_get_uuid(b_channel)); switch_channel_set_variable(b_channel, "other_loopback_leg_uuid", switch_channel_get_uuid(channel)); if (switch_core_session_thread_launch(b_session) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error spawning thread\n"); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); goto end; } } else if ((tech_pvt->other_session = switch_core_session_locate(tech_pvt->other_uuid))) { tech_pvt->other_tech_pvt = switch_core_session_get_private(tech_pvt->other_session); tech_pvt->other_channel = switch_core_session_get_channel(tech_pvt->other_session); } if (!tech_pvt->other_session) { switch_clear_flag_locked(tech_pvt, TFLAG_LINKED); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); goto end; } switch_channel_set_variable(channel, "loopback_leg", switch_test_flag(tech_pvt, TFLAG_BLEG) ? "B" : "A"); switch_channel_set_state(channel, CS_ROUTING); end: return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(switch_status_t) switch_core_session_set_real_read_codec(switch_core_session_t *session, switch_codec_t *codec) { switch_event_t *event; switch_channel_t *channel = switch_core_session_get_channel(session); char tmp[30]; switch_status_t status = SWITCH_STATUS_SUCCESS; int changed_read_codec = 0; switch_mutex_lock(session->codec_read_mutex); if (codec && (!codec->implementation || !switch_core_codec_ready(codec))) { codec = NULL; } if (codec) { /* set real_read_codec and read_codec */ if (!session->real_read_codec) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Original read codec set to %s:%d\n", switch_channel_get_name(session->channel), codec->implementation->iananame, codec->implementation->ianacode); session->read_codec = session->real_read_codec = codec; changed_read_codec = 1; if (codec->implementation) { session->read_impl = *codec->implementation; session->real_read_impl = *codec->implementation; } else { memset(&session->read_impl, 0, sizeof(session->read_impl)); } } else { /* replace real_read_codec */ switch_codec_t *cur_codec; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Original read codec replaced with %s:%d\n", switch_channel_get_name(session->channel), codec->implementation->iananame, codec->implementation->ianacode); /* Set real_read_codec to front of the list of read_codecs */ cur_codec = session->read_codec; while (cur_codec != NULL) { if (cur_codec->next == session->real_read_codec) { cur_codec->next = codec; break; } cur_codec = cur_codec->next; } session->real_read_codec = codec; /* set read_codec with real_read_codec if it no longer is ready */ if (!switch_core_codec_ready(session->read_codec)) { session->read_codec = codec; changed_read_codec = 1; if (codec->implementation) { session->read_impl = *codec->implementation; session->real_read_impl = *codec->implementation; } else { memset(&session->read_impl, 0, sizeof(session->read_impl)); } } } /* force media bugs to copy the read codec from the next frame */ switch_thread_rwlock_wrlock(session->bug_rwlock); if (switch_core_codec_ready(&session->bug_codec)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Destroying BUG Codec %s:%d\n", session->bug_codec.implementation->iananame, session->bug_codec.implementation->ianacode); switch_core_codec_destroy(&session->bug_codec); } switch_thread_rwlock_unlock(session->bug_rwlock); } else { status = SWITCH_STATUS_FALSE; goto end; } if (changed_read_codec && session->read_codec && session->read_impl.decoded_bytes_per_packet) { if (switch_event_create(&event, SWITCH_EVENT_CODEC) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(session->channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-read-codec-name", session->read_impl.iananame); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-rate", "%d", session->read_impl.actual_samples_per_second); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-bit-rate", "%d", session->read_impl.bits_per_second); if (session->read_impl.actual_samples_per_second != session->read_impl.samples_per_second) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-reported-read-codec-rate", "%d", session->read_impl.samples_per_second); } switch_event_fire(&event); } switch_channel_set_variable(channel, "read_codec", session->read_impl.iananame); switch_snprintf(tmp, sizeof(tmp), "%d", session->read_impl.actual_samples_per_second); switch_channel_set_variable(channel, "read_rate", tmp); session->raw_read_frame.codec = session->read_codec; session->raw_write_frame.codec = session->read_codec; session->enc_read_frame.codec = session->read_codec; session->enc_write_frame.codec = session->read_codec; } end: if (session->read_codec) { switch_channel_set_flag(channel, CF_MEDIA_SET); } switch_mutex_unlock(session->codec_read_mutex); return status; }
/** * Start execution of call receivefax component * @param call the call to receive fax from * @param msg the original request * @param session_data the call's session */ static iks *start_receivefax_component(struct rayo_actor *call, struct rayo_message *msg, void *session_data) { iks *iq = msg->payload; switch_core_session_t *session = (switch_core_session_t *)session_data; struct receivefax_component *receivefax_component = NULL; iks *receivefax = iks_find(iq, "receivefax"); iks *response = NULL; switch_event_t *execute_event = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); switch_memory_pool_t *pool; int file_no; /* validate attributes */ if (!VALIDATE_RAYO_RECEIVEFAX(receivefax)) { return iks_new_error(iq, STANZA_ERROR_BAD_REQUEST); } /* fax is only allowed if the call is not currently joined */ if (rayo_call_is_joined(RAYO_CALL(call))) { return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "can't receive fax on a joined call"); } if (rayo_call_is_faxing(RAYO_CALL(call))) { return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "fax already in progress"); } /* create receivefax component */ switch_core_new_memory_pool(&pool); receivefax_component = switch_core_alloc(pool, sizeof(*receivefax_component)); rayo_component_init((struct rayo_component *)receivefax_component, pool, RAT_CALL_COMPONENT, "receivefax", NULL, call, iks_find_attrib(iq, "from")); file_no = rayo_actor_seq_next(call); receivefax_component->filename = switch_core_sprintf(pool, "%s%s%s-%d.tif", globals.file_prefix, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session), file_no); if (!strncmp(receivefax_component->filename, "http://", 7) || !strncmp(receivefax_component->filename, "https://", 8)) { /* This is an HTTP URL, need to PUT after fax is received */ receivefax_component->local_filename = switch_core_sprintf(pool, "%s%s%s-%d", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session), file_no); receivefax_component->http_put_after_receive = 1; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s save fax to HTTP URL\n", RAYO_JID(receivefax_component)); } else { /* assume file.. */ receivefax_component->local_filename = receivefax_component->filename; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s save fax to local file\n", RAYO_JID(receivefax_component)); } /* add channel variable so that fax component can be located from fax events */ switch_channel_set_variable(channel, "rayo_fax_jid", RAYO_JID(receivefax_component)); /* clear fax result variables */ switch_channel_set_variable(channel, "fax_success", NULL); switch_channel_set_variable(channel, "fax_result_code", NULL); switch_channel_set_variable(channel, "fax_result_text", NULL); switch_channel_set_variable(channel, "fax_document_transferred_pages", NULL); switch_channel_set_variable(channel, "fax_document_total_pages", NULL); switch_channel_set_variable(channel, "fax_image_resolution", NULL); switch_channel_set_variable(channel, "fax_image_size", NULL); switch_channel_set_variable(channel, "fax_bad_rows", NULL); switch_channel_set_variable(channel, "fax_transfer_rate", NULL); switch_channel_set_variable(channel, "fax_ecm_used", NULL); switch_channel_set_variable(channel, "fax_local_station_id", NULL); switch_channel_set_variable(channel, "fax_remote_station_id", NULL); /* clear fax interrupt variable */ switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", NULL); rayo_call_set_faxing(RAYO_CALL(call), 1); /* execute rxfax APP */ if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", "rxfax"); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", receivefax_component->local_filename); if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) { switch_channel_set_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA); } if (switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to rxfax (queue event failed)"); if (execute_event) { switch_event_destroy(&execute_event); } rayo_call_set_faxing(RAYO_CALL(call), 0); RAYO_UNLOCK(receivefax_component); } else { /* component starting... */ rayo_component_send_start(RAYO_COMPONENT(receivefax_component), iq); } } else { response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to create rxfax event"); rayo_call_set_faxing(RAYO_CALL(call), 0); RAYO_UNLOCK(receivefax_component); } return response; }
SWITCH_DECLARE(switch_status_t) switch_core_session_set_write_codec(switch_core_session_t *session, switch_codec_t *codec) { switch_event_t *event; switch_channel_t *channel = switch_core_session_get_channel(session); char tmp[30]; switch_status_t status = SWITCH_STATUS_SUCCESS; switch_mutex_lock(session->codec_write_mutex); if (!codec || !codec->implementation || !switch_core_codec_ready(codec)) { if (session->real_write_codec) { session->write_codec = session->real_write_codec; session->write_impl = *session->real_write_codec->implementation; session->real_write_codec = NULL; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot set NULL codec!\n"); status = SWITCH_STATUS_FALSE; goto end; } } else if (session->write_codec) { if (session->real_write_codec) { if (codec == session->real_write_codec) { session->write_codec = codec; session->write_impl = *codec->implementation; session->real_write_codec = NULL; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot double-set codec!\n"); status = SWITCH_STATUS_FALSE; goto end; } } else { session->real_write_codec = session->write_codec; session->write_codec = codec; session->write_impl = *codec->implementation; } } else { session->write_codec = codec; session->write_impl = *codec->implementation; } if (session->write_codec && codec && session->write_impl.codec_id) { if (switch_event_create(&event, SWITCH_EVENT_CODEC) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(session->channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Name", session->write_impl.iananame); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Rate", "%d", session->write_impl.actual_samples_per_second); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-codec-bit-rate", "%d", session->write_impl.bits_per_second); if (session->write_impl.actual_samples_per_second != session->write_impl.samples_per_second) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Reported-Write-Codec-Rate", "%d", session->write_impl.actual_samples_per_second); } switch_event_fire(&event); } switch_channel_set_variable(channel, "write_codec", session->write_impl.iananame); switch_snprintf(tmp, sizeof(tmp), "%d", session->write_impl.actual_samples_per_second); switch_channel_set_variable(channel, "write_rate", tmp); } end: switch_mutex_unlock(session->codec_write_mutex); return status; }
static void switch_core_standard_on_routing(switch_core_session_t *session) { switch_dialplan_interface_t *dialplan_interface = NULL; switch_caller_profile_t *caller_profile; switch_caller_extension_t *extension = NULL; char *expanded = NULL; char *dpstr = NULL; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard ROUTING\n", switch_channel_get_name(session->channel)); switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session)); if ((switch_channel_test_flag(session->channel, CF_ANSWERED) || switch_channel_test_flag(session->channel, CF_EARLY_MEDIA) || switch_channel_test_flag(session->channel, CF_SIGNAL_BRIDGE_TTL)) && switch_channel_test_flag(session->channel, CF_PROXY_MODE)) { switch_ivr_media(session->uuid_str, SMF_NONE); } if ((caller_profile = switch_channel_get_caller_profile(session->channel)) == 0) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't get profile!\n"); switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); return; } else { char *dp[25]; int argc, x, count = 0; if ((extension = switch_channel_get_queued_extension(session->channel))) { switch_channel_set_caller_extension(session->channel, extension); switch_channel_set_state(session->channel, CS_EXECUTE); goto end; } if (!zstr(caller_profile->dialplan)) { if ((dpstr = switch_core_session_strdup(session, caller_profile->dialplan))) { expanded = switch_channel_expand_variables(session->channel, dpstr); argc = switch_separate_string(expanded, ',', dp, (sizeof(dp) / sizeof(dp[0]))); for (x = 0; x < argc; x++) { char *dpname = dp[x]; char *dparg = NULL; if (dpname) { if ((dparg = strchr(dpname, ':'))) { *dparg++ = '\0'; } } else { continue; } if (!(dialplan_interface = switch_loadable_module_get_dialplan_interface(dpname))) { continue; } count++; extension = dialplan_interface->hunt_function(session, dparg, NULL); UNPROTECT_INTERFACE(dialplan_interface); if (extension) { switch_channel_set_caller_extension(session->channel, extension); switch_channel_set_state(session->channel, CS_EXECUTE); goto end; } } } } if (!count) { if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { if (switch_channel_test_flag(session->channel, CF_ANSWERED)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No Dialplan on answered channel, changing state to HANGUP\n"); switch_channel_hangup(session->channel, SWITCH_CAUSE_NO_ROUTE_DESTINATION); } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No Dialplan, changing state to CONSUME_MEDIA\n"); switch_channel_set_state(session->channel, CS_CONSUME_MEDIA); } goto end; } } } if (!extension) { if (switch_ivr_blind_transfer_ack(session, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "No Route, Aborting\n"); switch_channel_hangup(session->channel, SWITCH_CAUSE_NO_ROUTE_DESTINATION); } } end: if (expanded && dpstr && expanded != dpstr) { free(expanded); } }
/** * Handle fax completion event from FreeSWITCH core * @param event received from FreeSWITCH core. It will be destroyed by the core after this function returns. */ static void on_execute_complete_event(switch_event_t *event) { const char *application = switch_event_get_header(event, "Application"); if (!zstr(application) && (!strcmp(application, "rxfax") || !strcmp(application, "txfax"))) { int is_rxfax = !strcmp(application, "rxfax"); const char *uuid = switch_event_get_header(event, "Unique-ID"); const char *fax_jid = switch_event_get_header(event, "variable_rayo_fax_jid"); struct rayo_actor *component; if (!zstr(fax_jid) && (component = RAYO_LOCATE(fax_jid))) { iks *result; iks *complete; iks *fax; int have_fax_document = 1; switch_core_session_t *session; switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "Got result for %s\n", fax_jid); /* clean up channel */ session = switch_core_session_locate(uuid); if (session) { switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", NULL); switch_core_session_rwunlock(session); } /* RX only: transfer HTTP document and delete local copy */ if (is_rxfax && RECEIVEFAX_COMPONENT(component)->http_put_after_receive && switch_file_exists(RECEIVEFAX_COMPONENT(component)->local_filename, RAYO_POOL(component)) == SWITCH_STATUS_SUCCESS) { switch_stream_handle_t stream = { 0 }; SWITCH_STANDARD_STREAM(stream); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s PUT fax to %s\n", RAYO_JID(component), RECEIVEFAX_COMPONENT(component)->filename); switch_api_execute("http_put", RECEIVEFAX_COMPONENT(component)->filename, NULL, &stream); /* check if successful */ if (!zstr(stream.data) && strncmp(stream.data, "+OK", 3)) { /* PUT failed */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s PUT fax to %s failed: %s\n", RAYO_JID(component), RECEIVEFAX_COMPONENT(component)->filename, (char *)stream.data); have_fax_document = 0; } switch_safe_free(stream.data) switch_file_remove(RECEIVEFAX_COMPONENT(component)->local_filename, RAYO_POOL(component)); } /* successful fax? */ if (have_fax_document && switch_true(switch_event_get_header(event, "variable_fax_success"))) { result = rayo_component_create_complete_event(RAYO_COMPONENT(component), FAX_FINISH); } else if (have_fax_document && FAX_COMPONENT(component)->stop) { result = rayo_component_create_complete_event(RAYO_COMPONENT(component), COMPONENT_COMPLETE_STOP); } else { result = rayo_component_create_complete_event(RAYO_COMPONENT(component), COMPONENT_COMPLETE_ERROR); } complete = iks_find(result, "complete"); /* RX only: add fax document information */ if (is_rxfax && have_fax_document) { const char *pages = switch_event_get_header(event, "variable_fax_document_transferred_pages"); if (!zstr(pages) && switch_is_number(pages) && atoi(pages) > 0) { const char *resolution = switch_event_get_header(event, "variable_fax_file_image_resolution"); const char *size = switch_event_get_header(event, "variable_fax_image_size"); fax = iks_insert(complete, "fax"); iks_insert_attrib(fax, "xmlns", RAYO_FAX_COMPLETE_NS); if (RECEIVEFAX_COMPONENT(component)->http_put_after_receive) { iks_insert_attrib(fax, "url", RECEIVEFAX_COMPONENT(component)->filename); } else { /* convert absolute path to file:// URI */ iks_insert_attrib_printf(fax, "url", "file://%s", RECEIVEFAX_COMPONENT(component)->filename); } if (!zstr(resolution)) { iks_insert_attrib(fax, "resolution", resolution); } if (!zstr(size)) { iks_insert_attrib(fax, "size", size); } iks_insert_attrib(fax, "pages", pages); } } /* add metadata from event */ insert_fax_metadata(event, "fax_success", complete); insert_fax_metadata(event, "fax_result_code", complete); insert_fax_metadata(event, "fax_result_text", complete); insert_fax_metadata(event, "fax_document_transferred_pages", complete); insert_fax_metadata(event, "fax_document_total_pages", complete); insert_fax_metadata(event, "fax_image_resolution", complete); insert_fax_metadata(event, "fax_image_size", complete); insert_fax_metadata(event, "fax_bad_rows", complete); insert_fax_metadata(event, "fax_transfer_rate", complete); insert_fax_metadata(event, "fax_ecm_used", complete); insert_fax_metadata(event, "fax_local_station_id", complete); insert_fax_metadata(event, "fax_remote_station_id", complete); /* flag faxing as done */ rayo_call_set_faxing(RAYO_CALL(RAYO_COMPONENT(component)->parent), 0); rayo_component_send_complete_event(RAYO_COMPONENT(component), result); RAYO_UNLOCK(component); } } }
static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause) { char name[128]; if (session) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_channel_clear_flag(channel, CF_PROXY_MEDIA); switch_channel_clear_flag(channel, CF_PROXY_MODE); switch_channel_pre_answer(channel); } if ((*new_session = switch_core_session_request(loopback_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, pool)) != 0) { private_t *tech_pvt; switch_channel_t *channel; switch_caller_profile_t *caller_profile; switch_core_session_add_stream(*new_session, NULL); if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) { channel = switch_core_session_get_channel(*new_session); switch_snprintf(name, sizeof(name), "loopback/%s-a", outbound_profile->destination_number); switch_channel_set_name(channel, name); if (tech_init(tech_pvt, *new_session, session ? switch_core_session_get_read_codec(session) : NULL) != SWITCH_STATUS_SUCCESS) { switch_core_session_destroy(new_session); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); switch_core_session_destroy(new_session); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } if (outbound_profile) { char *dialplan = NULL, *context = NULL; caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); caller_profile->source = switch_core_strdup(caller_profile->pool, modname); if (!strncasecmp(caller_profile->destination_number, "app=", 4)) { char *dest = switch_core_session_strdup(*new_session, caller_profile->destination_number); char *app = dest + 4; char *arg = NULL; if ((arg = strchr(app, ':'))) { *arg++ = '\0'; } switch_channel_set_variable(channel, "loopback_app", app); if (arg) { switch_channel_set_variable(channel, "loopback_app_arg", arg); } caller_profile->destination_number = switch_core_strdup(caller_profile->pool, app); } if ((context = strchr(caller_profile->destination_number, '/'))) { *context++ = '\0'; if ((dialplan = strchr(context, '/'))) { *dialplan++ = '\0'; } if (!zstr(context)) { caller_profile->context = switch_core_strdup(caller_profile->pool, context); } if (!zstr(dialplan)) { caller_profile->dialplan = switch_core_strdup(caller_profile->pool, dialplan); } } if (zstr(caller_profile->context)) { caller_profile->context = switch_core_strdup(caller_profile->pool, "default"); } if (zstr(caller_profile->dialplan)) { caller_profile->dialplan = switch_core_strdup(caller_profile->pool, "xml"); } switch_snprintf(name, sizeof(name), "loopback/%s-a", caller_profile->destination_number); switch_channel_set_name(channel, name); switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND); switch_channel_set_caller_profile(channel, caller_profile); tech_pvt->caller_profile = caller_profile; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_ERROR, "Doh! no caller profile\n"); switch_core_session_destroy(new_session); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } switch_channel_set_state(channel, CS_INIT); return SWITCH_CAUSE_SUCCESS; } return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; }
static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event) { const char *command = switch_event_get_header(event, "command"); switch_channel_t *channel = switch_core_session_get_channel(session); crtp_private_t *tech_pvt = switch_core_session_get_private(session); char *codec = switch_event_get_header_nil(event, kCODEC); char *szptime = switch_event_get_header_nil(event, kPTIME); char *szrate = switch_event_get_header_nil(event, kRATE); char *szpt = switch_event_get_header_nil(event, kPT); int ptime = !zstr(szptime) ? atoi(szptime) : 0, rate = !zstr(szrate) ? atoi(szrate) : 8000, pt = !zstr(szpt) ? atoi(szpt) : 0; if (!zstr(command) && !strcasecmp(command, "media_modify")) { /* Compare parameters */ if (compare_var(event, channel, kREMOTEADDR) || compare_var(event, channel, kREMOTEPORT)) { char *remote_addr = switch_event_get_header(event, kREMOTEADDR); char *szremote_port = switch_event_get_header(event, kREMOTEPORT); switch_port_t remote_port = !zstr(szremote_port) ? atoi(szremote_port) : 0; const char *err; switch_channel_set_variable(channel, kREMOTEADDR, remote_addr); switch_channel_set_variable(channel, kREMOTEPORT, szremote_port); if (switch_rtp_set_remote_address(tech_pvt->rtp_session, remote_addr, remote_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error setting RTP remote address: %s\n", err); } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set RTP remote: %s:%d\n", remote_addr, (int)remote_port); tech_pvt->mode = RTP_SENDRECV; } } if (compare_var(event, channel, kCODEC) || compare_var(event, channel, kPTIME) || compare_var(event, channel, kPT) || compare_var(event, channel, kRATE)) { /* Reset codec */ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Switching codec updating \n"); if (switch_core_codec_init(&tech_pvt->read_codec, codec, NULL, rate, ptime, 1, /*SWITCH_CODEC_FLAG_ENCODE |*/ SWITCH_CODEC_FLAG_DECODE, NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); goto fail; } else { if (switch_core_codec_init(&tech_pvt->write_codec, codec, NULL, rate, ptime, 1, SWITCH_CODEC_FLAG_ENCODE /*| SWITCH_CODEC_FLAG_DECODE*/, NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); goto fail; } } if (switch_core_session_set_read_codec(session, &tech_pvt->read_codec) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set read codec?\n"); goto fail; } if (switch_core_session_set_write_codec(session, &tech_pvt->write_codec) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set write codec?\n"); goto fail; } switch_rtp_set_default_payload(tech_pvt->rtp_session, pt); //switch_rtp_set_recv_pt(tech_pvt->rtp_session, pt); } if (compare_var(event, channel, kRFC2833PT)) { const char *szpt = switch_channel_get_variable(channel, kRFC2833PT); int pt = !zstr(szpt) ? atoi(szpt) : 0; switch_channel_set_variable(channel, kRFC2833PT, szpt); switch_rtp_set_telephony_event(tech_pvt->rtp_session, pt); } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Received unknown command [%s] in event.\n", !command ? "null" : command); } return SWITCH_STATUS_SUCCESS; fail: if (tech_pvt) { if (tech_pvt->read_codec.implementation) { switch_core_codec_destroy(&tech_pvt->read_codec); } if (tech_pvt->write_codec.implementation) { switch_core_codec_destroy(&tech_pvt->write_codec); } } if (session) { switch_core_session_destroy(&session); } return SWITCH_STATUS_FALSE; }
/** * Start execution of call sendfax component * @param call the call to send fax to * @param msg the original request * @param session_data the call's session */ static iks *start_sendfax_component(struct rayo_actor *call, struct rayo_message *msg, void *session_data) { iks *iq = msg->payload; switch_core_session_t *session = (switch_core_session_t *)session_data; struct fax_component *sendfax_component = NULL; iks *sendfax = iks_find(iq, "sendfax"); iks *response = NULL; switch_event_t *execute_event = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); switch_memory_pool_t *pool; iks *document; const char *fax_document; const char *fax_header; const char *fax_identity; const char *pages; /* validate attributes */ if (!VALIDATE_RAYO_SENDFAX(sendfax)) { return iks_new_error(iq, STANZA_ERROR_BAD_REQUEST); } /* fax is only allowed if the call is not currently joined */ if (rayo_call_is_joined(RAYO_CALL(call))) { return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "can't send fax on a joined call"); } if (rayo_call_is_faxing(RAYO_CALL(call))) { return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "fax already in progress"); } /* get fax document */ document = iks_find(sendfax, "document"); if (!document) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "missing document"); } fax_document = iks_find_attrib_soft(document, "url"); if (zstr(fax_document)) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "missing document url"); } /* is valid URL type? */ if (!strncasecmp(fax_document, "http://", 7) || !strncasecmp(fax_document, "https://", 8)) { switch_stream_handle_t stream = { 0 }; SWITCH_STANDARD_STREAM(stream); /* need to fetch document from server... */ switch_api_execute("http_get", fax_document, session, &stream); if (!zstr(stream.data) && !strncmp(fax_document, SWITCH_PATH_SEPARATOR, strlen(SWITCH_PATH_SEPARATOR))) { fax_document = switch_core_session_strdup(session, stream.data); } else { switch_safe_free(stream.data); return iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to fetch document"); } switch_safe_free(stream.data); } else if (!strncasecmp(fax_document, "file://", 7)) { fax_document = fax_document + 7; if (zstr(fax_document)) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "invalid file:// url"); } } else if (strncasecmp(fax_document, SWITCH_PATH_SEPARATOR, strlen(SWITCH_PATH_SEPARATOR))) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "unsupported url type"); } /* does document exist? */ if (switch_file_exists(fax_document, pool) != SWITCH_STATUS_SUCCESS) { return iks_new_error_detailed_printf(iq, STANZA_ERROR_BAD_REQUEST, "file not found: %s", fax_document); } /* get fax identity and header */ fax_identity = iks_find_attrib_soft(document, "identity"); if (!zstr(fax_identity)) { switch_channel_set_variable(channel, "fax_ident", fax_identity); } else { switch_channel_set_variable(channel, "fax_ident", NULL); } fax_header = iks_find_attrib_soft(document, "header"); if (!zstr(fax_header)) { switch_channel_set_variable(channel, "fax_header", fax_header); } else { switch_channel_set_variable(channel, "fax_header", NULL); } /* get pages to send */ pages = iks_find_attrib_soft(document, "pages"); if (!zstr(pages)) { if (switch_regex_match(pages, "[1-9][0-9]*(-[1-9][0-9]*)?") == SWITCH_STATUS_FALSE) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "invalid pages value"); } else { int start = 0; int end = 0; char *pages_dup = switch_core_session_strdup(session, pages); char *sep = strchr(pages_dup, '-'); if (sep) { *sep = '\0'; sep++; end = atoi(sep); } start = atoi(pages_dup); if (end && end < start) { return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "invalid pages value"); } switch_channel_set_variable(channel, "fax_start_page", pages_dup); switch_channel_set_variable(channel, "fax_end_page", sep); } } else { switch_channel_set_variable(channel, "fax_start_page", NULL); switch_channel_set_variable(channel, "fax_end_page", NULL); } /* create sendfax component */ switch_core_new_memory_pool(&pool); sendfax_component = switch_core_alloc(pool, sizeof(*sendfax_component)); rayo_component_init((struct rayo_component *)sendfax_component, pool, RAT_CALL_COMPONENT, "sendfax", NULL, call, iks_find_attrib(iq, "from")); /* add channel variable so that fax component can be located from fax events */ switch_channel_set_variable(channel, "rayo_fax_jid", RAYO_JID(sendfax_component)); /* clear fax result variables */ switch_channel_set_variable(channel, "fax_success", NULL); switch_channel_set_variable(channel, "fax_result_code", NULL); switch_channel_set_variable(channel, "fax_result_text", NULL); switch_channel_set_variable(channel, "fax_document_transferred_pages", NULL); switch_channel_set_variable(channel, "fax_document_total_pages", NULL); switch_channel_set_variable(channel, "fax_image_resolution", NULL); switch_channel_set_variable(channel, "fax_image_size", NULL); switch_channel_set_variable(channel, "fax_bad_rows", NULL); switch_channel_set_variable(channel, "fax_transfer_rate", NULL); switch_channel_set_variable(channel, "fax_ecm_used", NULL); switch_channel_set_variable(channel, "fax_local_station_id", NULL); switch_channel_set_variable(channel, "fax_remote_station_id", NULL); /* clear fax interrupt variable */ switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", NULL); rayo_call_set_faxing(RAYO_CALL(call), 1); /* execute txfax APP */ if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute"); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", "txfax"); switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", fax_document); if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) { switch_channel_set_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA); } if (switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to txfax (queue event failed)"); if (execute_event) { switch_event_destroy(&execute_event); } rayo_call_set_faxing(RAYO_CALL(call), 0); RAYO_UNLOCK(sendfax_component); } else { /* component starting... */ rayo_component_send_start(RAYO_COMPONENT(sendfax_component), iq); } } else { response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to create txfax event"); rayo_call_set_faxing(RAYO_CALL(call), 0); RAYO_UNLOCK(sendfax_component); } return response; }