static switch_status_t my_on_reporting(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_status_t status = SWITCH_STATUS_SUCCESS; const char *template_str = NULL; char *expanded_vars = NULL, *sql = NULL; if (globals.shutdown) { return SWITCH_STATUS_SUCCESS; } if (!((globals.legs & CDR_LEG_A) && (globals.legs & CDR_LEG_B))) { if ((globals.legs & CDR_LEG_A)) { if (switch_channel_get_originator_caller_profile(channel)) { return SWITCH_STATUS_SUCCESS; } } else { if (switch_channel_get_originatee_caller_profile(channel)) { return SWITCH_STATUS_SUCCESS; } } } if (globals.debug) { switch_event_t *event; if (switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { char *buf; switch_channel_event_set_data(channel, event); switch_event_serialize(event, &buf, SWITCH_FALSE); switch_assert(buf); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "CHANNEL_DATA:\n%s\n", buf); switch_event_destroy(&event); switch_safe_free(buf); } } template_str = (const char *) switch_core_hash_find(globals.template_hash, globals.default_template); if (!template_str) { template_str = default_template; } expanded_vars = switch_channel_expand_variables(channel, template_str); if (!expanded_vars) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error expanding CDR variables.\n"); return SWITCH_STATUS_FALSE; } sql = switch_mprintf("INSERT INTO %s VALUES (%s)", globals.db_table, expanded_vars); assert(sql); write_cdr(sql); switch_safe_free(sql); if (expanded_vars != template_str) { switch_safe_free(expanded_vars); } return status; }
static void api_hook(switch_core_session_t *session, const char *hook_var, int use_session) { if (!zstr(hook_var)) { switch_stream_handle_t stream = { 0 }; char *cmd = switch_core_session_strdup(session, hook_var); char *arg = NULL; char *expanded = NULL; if ((arg = strchr(cmd, ':')) && *(arg + 1) == ':') { *arg++ = '\0'; *arg++ = '\0'; } else { if ((arg = strchr(cmd, ' '))) { *arg++ = '\0'; } } SWITCH_STANDARD_STREAM(stream); switch_channel_get_variables(session->channel, &stream.param_event); switch_channel_event_set_data(session->channel, stream.param_event); expanded = switch_channel_expand_variables(session->channel, arg); switch_api_execute(cmd, expanded, use_session ? session : NULL, &stream); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Hangup Command %s %s(%s):\n%s\n", use_session ? "with Session" : "with no Session", cmd, switch_str_nil(expanded), switch_str_nil((char *) stream.data) ); if (expanded != arg) { switch_safe_free(expanded); } switch_safe_free(stream.data); } }
SWITCH_DECLARE(switch_status_t) switch_core_session_set_video_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; if (!codec || !codec->implementation || !switch_core_codec_ready(codec)) { if (session->video_write_codec) { session->video_write_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-write-codec-name", codec->implementation->iananame); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-video-write-codec-rate", "%d", codec->implementation->actual_samples_per_second); switch_event_fire(&event); } switch_channel_set_variable(channel, "video_write_codec", codec->implementation->iananame); switch_snprintf(tmp, sizeof(tmp), "%d", codec->implementation->actual_samples_per_second); switch_channel_set_variable(channel, "video_write_rate", tmp); session->video_write_codec = codec; session->video_write_impl = *codec->implementation; end: return status; }
static void event_handler(switch_event_t *event) { if (process_event(event) != SWITCH_STATUS_SUCCESS) { const char *peer_uuid = switch_event_get_header(event, "variable_signal_bond"); switch_core_session_t *peer_session = NULL; switch_channel_t *peer_channel = NULL; switch_event_t *peer_event = NULL; if (!peer_uuid) { return; } if (!(peer_session = switch_core_session_locate(peer_uuid))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cant locate peer session for uuid %s\n", peer_uuid); return; } peer_channel = switch_core_session_get_channel(peer_session); if (switch_event_create(&peer_event, SWITCH_EVENT_CHANNEL_BRIDGE) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cant create bridge event for peer channel %s\n", peer_uuid); goto end; } switch_channel_event_set_data(peer_channel, peer_event); end: switch_core_session_rwunlock(peer_session); if (peer_event) { process_event(peer_event); switch_event_destroy(&peer_event); } } }
SWITCH_DECLARE(void) CoreSession::setEventData(Event *e) { this_check_void(); sanity_check_noreturn; if (channel && e->event) { switch_channel_event_set_data(channel, e->event); } }
static switch_status_t dialplan_xml_locate(switch_core_session_t *session, switch_caller_profile_t *caller_profile, switch_xml_t *root, switch_xml_t *node) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_status_t status = SWITCH_STATUS_GENERR; switch_event_t *params = NULL; switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS); switch_assert(params); switch_channel_event_set_data(channel, params); switch_caller_profile_event_set_data(caller_profile, "Hunt", params); status = switch_xml_locate("dialplan", NULL, NULL, NULL, root, node, params, SWITCH_FALSE); switch_event_destroy(¶ms); return status; }
static void switch_core_media_bug_destroy(switch_media_bug_t *bug) { switch_event_t *event = NULL; if (bug->raw_read_buffer) { switch_buffer_destroy(&bug->raw_read_buffer); } if (bug->raw_write_buffer) { switch_buffer_destroy(&bug->raw_write_buffer); } if (switch_event_create(&event, SWITCH_EVENT_MEDIA_BUG_STOP) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Function", "%s", bug->function); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Target", "%s", bug->target); if (bug->session) switch_channel_event_set_data(bug->session->channel, event); switch_event_fire(&event); } }
SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) { switch_io_event_hook_read_frame_t *ptr; switch_status_t status = SWITCH_STATUS_FALSE; int need_codec, perfect, do_bugs = 0, do_resample = 0, is_cng = 0; switch_codec_implementation_t codec_impl; unsigned int flag = 0; switch_assert(session != NULL); if (switch_mutex_trylock(session->codec_read_mutex) == SWITCH_STATUS_SUCCESS) { switch_mutex_unlock(session->codec_read_mutex); } else { switch_cond_next(); *frame = &runtime.dummy_cng_frame; return SWITCH_STATUS_SUCCESS; } if (!(session->read_codec && session->read_codec->implementation && switch_core_codec_ready(session->read_codec))) { if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || switch_channel_get_state(session->channel) == CS_HIBERNATE) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s reading on a session with no media!\n", switch_channel_get_name(session->channel)); switch_cond_next(); *frame = &runtime.dummy_cng_frame; return SWITCH_STATUS_SUCCESS; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION); return SWITCH_STATUS_FALSE; } switch_mutex_lock(session->codec_read_mutex); if (!switch_core_codec_ready(session->read_codec)) { switch_mutex_unlock(session->codec_read_mutex); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION); *frame = &runtime.dummy_cng_frame; return SWITCH_STATUS_FALSE; } switch_mutex_lock(session->read_codec->mutex); top: if (session->dmachine && !switch_channel_test_flag(session->channel, CF_BROADCAST)) { switch_ivr_dmachine_ping(session->dmachine, NULL); } if (switch_channel_down(session->channel) || !switch_core_codec_ready(session->read_codec)) { *frame = NULL; status = SWITCH_STATUS_FALSE; goto even_more_done; } status = SWITCH_STATUS_FALSE; need_codec = perfect = 0; *frame = NULL; if (session->read_codec && !session->track_id && session->track_duration) { if (session->read_frame_count == 0) { switch_event_t *event; session->read_frame_count = (session->read_impl.actual_samples_per_second / session->read_impl.samples_per_packet) * session->track_duration; switch_event_create(&event, SWITCH_EVENT_SESSION_HEARTBEAT); switch_channel_event_set_data(session->channel, event); switch_event_fire(&event); } else { session->read_frame_count--; } } if (switch_channel_test_flag(session->channel, CF_HOLD)) { switch_yield(session->read_impl.microseconds_per_packet); status = SWITCH_STATUS_BREAK; goto even_more_done; } if (session->endpoint_interface->io_routines->read_frame) { switch_mutex_unlock(session->read_codec->mutex); switch_mutex_unlock(session->codec_read_mutex); if ((status = session->endpoint_interface->io_routines->read_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) { for (ptr = session->event_hooks.read_frame; ptr; ptr = ptr->next) { if ((status = ptr->read_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) { break; } } } if (!SWITCH_READ_ACCEPTABLE(status) || !session->read_codec || !switch_core_codec_ready(session->read_codec)) { *frame = NULL; return SWITCH_STATUS_FALSE; } switch_mutex_lock(session->codec_read_mutex); if (!switch_core_codec_ready(session->read_codec)) { switch_mutex_unlock(session->codec_read_mutex); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no read codec.\n", switch_channel_get_name(session->channel)); switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION); *frame = &runtime.dummy_cng_frame; return SWITCH_STATUS_FALSE; } switch_mutex_lock(session->read_codec->mutex); if (!switch_core_codec_ready(session->read_codec)) { *frame = NULL; status = SWITCH_STATUS_FALSE; goto even_more_done; } } if (status != SWITCH_STATUS_SUCCESS) { goto done; } if (!(*frame)) { goto done; } switch_assert(*frame != NULL); if (switch_test_flag(*frame, SFF_PROXY_PACKET)) { /* Fast PASS! */ status = SWITCH_STATUS_SUCCESS; goto done; } if (switch_test_flag(*frame, SFF_CNG)) { status = SWITCH_STATUS_SUCCESS; if (!session->bugs && !session->plc) { goto done; } is_cng = 1; } switch_assert((*frame)->codec != NULL); if (!(session->read_codec && (*frame)->codec && (*frame)->codec->implementation) && switch_core_codec_ready((*frame)->codec)) { status = SWITCH_STATUS_FALSE; goto done; } codec_impl = *(*frame)->codec->implementation; if (session->read_codec->implementation->impl_id != codec_impl.impl_id) { need_codec = TRUE; } if (codec_impl.actual_samples_per_second != session->read_impl.actual_samples_per_second) { do_resample = 1; } if (session->bugs && !need_codec) { do_bugs = 1; need_codec = 1; } if (switch_test_flag(session, SSF_READ_TRANSCODE) && !need_codec && switch_core_codec_ready(session->read_codec)) { switch_core_session_t *other_session; const char *uuid = switch_channel_get_variable(switch_core_session_get_channel(session), SWITCH_SIGNAL_BOND_VARIABLE); switch_clear_flag(session, SSF_READ_TRANSCODE); if (uuid && (other_session = switch_core_session_locate(uuid))) { switch_set_flag(other_session, SSF_READ_CODEC_RESET); switch_set_flag(other_session, SSF_READ_CODEC_RESET); switch_set_flag(other_session, SSF_WRITE_CODEC_RESET); switch_core_session_rwunlock(other_session); } } if (switch_test_flag(session, SSF_READ_CODEC_RESET)) { switch_core_codec_reset(session->read_codec); switch_clear_flag(session, SSF_READ_CODEC_RESET); } if (status == SWITCH_STATUS_SUCCESS && need_codec) { switch_frame_t *enc_frame, *read_frame = *frame; switch_set_flag(session, SSF_READ_TRANSCODE); if (!switch_test_flag(session, SSF_WARN_TRANSCODE)) { switch_core_session_message_t msg = { 0 }; msg.message_id = SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY; switch_core_session_receive_message(session, &msg); switch_set_flag(session, SSF_WARN_TRANSCODE); } if (read_frame->codec || is_cng) { session->raw_read_frame.datalen = session->raw_read_frame.buflen; if (is_cng) { if (session->plc) { plc_fillin(session->plc, session->raw_read_frame.data, read_frame->codec->implementation->decoded_bytes_per_packet / 2); is_cng = 0; flag &= !SFF_CNG; } else { memset(session->raw_read_frame.data, 255, read_frame->codec->implementation->decoded_bytes_per_packet); } session->raw_read_frame.timestamp = 0; session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet; session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); read_frame = &session->raw_read_frame; status = SWITCH_STATUS_SUCCESS; } else { switch_codec_t *use_codec = read_frame->codec; if (do_bugs) { switch_thread_rwlock_wrlock(session->bug_rwlock); if (!session->bugs) { do_bugs = 0; switch_thread_rwlock_unlock(session->bug_rwlock); goto done; } if (!switch_core_codec_ready(&session->bug_codec)) { switch_core_codec_copy(read_frame->codec, &session->bug_codec, NULL); } use_codec = &session->bug_codec; switch_thread_rwlock_unlock(session->bug_rwlock); switch_thread_rwlock_wrlock(session->bug_rwlock); if (!session->bugs) { do_bugs = 0; } switch_thread_rwlock_unlock(session->bug_rwlock); if (!do_bugs) goto done; } if (switch_test_flag(read_frame, SFF_PLC)) { session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet; session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); memset(session->raw_read_frame.data, 255, session->raw_read_frame.datalen); status = SWITCH_STATUS_SUCCESS; } else { status = switch_core_codec_decode(use_codec, session->read_codec, read_frame->data, read_frame->datalen, session->read_impl.actual_samples_per_second, session->raw_read_frame.data, &session->raw_read_frame.datalen, &session->raw_read_frame.rate, &read_frame->flags); } if (status == SWITCH_STATUS_SUCCESS) { if ((switch_channel_test_flag(session->channel, CF_JITTERBUFFER) || switch_channel_test_flag(session->channel, CF_CNG_PLC)) && !session->plc) { session->plc = plc_init(NULL); } if (session->plc) { if (switch_test_flag(read_frame, SFF_PLC)) { plc_fillin(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2); switch_clear_flag(read_frame, SFF_PLC); } else { plc_rx(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2); } } } } if (do_resample && ((status == SWITCH_STATUS_SUCCESS) || is_cng)) { status = SWITCH_STATUS_RESAMPLE; } switch (status) { case SWITCH_STATUS_RESAMPLE: if (!session->read_resampler) { switch_mutex_lock(session->resample_mutex); status = switch_resample_create(&session->read_resampler, read_frame->codec->implementation->actual_samples_per_second, session->read_impl.actual_samples_per_second, session->read_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 1); switch_mutex_unlock(session->resample_mutex); if (status != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to allocate resampler\n"); status = SWITCH_STATUS_FALSE; goto done; } } case SWITCH_STATUS_SUCCESS: session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); session->raw_read_frame.rate = read_frame->rate; if (read_frame->codec->implementation->samples_per_packet != session->read_impl.samples_per_packet) { session->raw_read_frame.timestamp = 0; } else { session->raw_read_frame.timestamp = read_frame->timestamp; } session->raw_read_frame.ssrc = read_frame->ssrc; session->raw_read_frame.seq = read_frame->seq; session->raw_read_frame.m = read_frame->m; session->raw_read_frame.payload = read_frame->payload; session->raw_read_frame.flags = 0; if (switch_test_flag(read_frame, SFF_PLC)) { session->raw_read_frame.flags |= SFF_PLC; } read_frame = &session->raw_read_frame; break; case SWITCH_STATUS_NOOP: if (session->read_resampler) { switch_mutex_lock(session->resample_mutex); switch_resample_destroy(&session->read_resampler); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating read resampler\n"); switch_mutex_unlock(session->resample_mutex); } status = SWITCH_STATUS_SUCCESS; break; case SWITCH_STATUS_BREAK: memset(session->raw_read_frame.data, 255, read_frame->codec->implementation->decoded_bytes_per_packet); session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet; session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t); session->raw_read_frame.timestamp = read_frame->timestamp; session->raw_read_frame.rate = read_frame->rate; session->raw_read_frame.ssrc = read_frame->ssrc; session->raw_read_frame.seq = read_frame->seq; session->raw_read_frame.m = read_frame->m; session->raw_read_frame.payload = read_frame->payload; session->raw_read_frame.flags = 0; if (switch_test_flag(read_frame, SFF_PLC)) { session->raw_read_frame.flags |= SFF_PLC; } read_frame = &session->raw_read_frame; status = SWITCH_STATUS_SUCCESS; break; case SWITCH_STATUS_NOT_INITALIZED: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n"); goto done; default: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s decoder error!\n", session->read_codec->codec_interface->interface_name); goto done; } } if (session->bugs) { switch_media_bug_t *bp; switch_bool_t ok = SWITCH_TRUE; int prune = 0; switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) { continue; } if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) { continue; } if (switch_test_flag(bp, SMBF_PRUNE)) { prune++; continue; } if (bp->ready && switch_test_flag(bp, SMBF_READ_STREAM)) { switch_mutex_lock(bp->read_mutex); switch_buffer_write(bp->raw_read_buffer, read_frame->data, read_frame->datalen); if (bp->callback) { ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ); } switch_mutex_unlock(bp->read_mutex); } if (ok && switch_test_flag(bp, SMBF_READ_REPLACE)) { do_bugs = 0; if (bp->callback) { bp->read_replace_frame_in = read_frame; bp->read_replace_frame_out = read_frame; if ((ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_REPLACE)) == SWITCH_TRUE) { read_frame = bp->read_replace_frame_out; } } } if ((bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) || ok == SWITCH_FALSE) { switch_set_flag(bp, SMBF_PRUNE); prune++; } } switch_thread_rwlock_unlock(session->bug_rwlock); if (prune) { switch_core_media_bug_prune(session); } } if (do_bugs) { goto done; } if (session->read_codec) { if (session->read_resampler) { short *data = read_frame->data; switch_mutex_lock(session->resample_mutex); switch_resample_process(session->read_resampler, data, (int) read_frame->datalen / 2); memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2); read_frame->samples = session->read_resampler->to_len; read_frame->datalen = session->read_resampler->to_len * 2; read_frame->rate = session->read_resampler->to_rate; switch_mutex_unlock(session->resample_mutex); } if (read_frame->datalen == session->read_impl.decoded_bytes_per_packet) { perfect = TRUE; } else { if (!session->raw_read_buffer) { switch_size_t bytes = session->read_impl.decoded_bytes_per_packet; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Engaging Read Buffer at %u bytes vs %u\n", (uint32_t) bytes, (uint32_t) (*frame)->datalen); switch_buffer_create_dynamic(&session->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, 0); } if (!switch_buffer_write(session->raw_read_buffer, read_frame->data, read_frame->datalen)) { status = SWITCH_STATUS_MEMERR; goto done; } } if (perfect || switch_buffer_inuse(session->raw_read_buffer) >= session->read_impl.decoded_bytes_per_packet) { if (perfect) { enc_frame = read_frame; session->raw_read_frame.rate = read_frame->rate; } else { session->raw_read_frame.datalen = (uint32_t) switch_buffer_read(session->raw_read_buffer, session->raw_read_frame.data, session->read_impl.decoded_bytes_per_packet); session->raw_read_frame.rate = session->read_impl.actual_samples_per_second; enc_frame = &session->raw_read_frame; } session->enc_read_frame.datalen = session->enc_read_frame.buflen; switch_assert(session->read_codec != NULL); switch_assert(enc_frame != NULL); switch_assert(enc_frame->data != NULL); status = switch_core_codec_encode(session->read_codec, enc_frame->codec, enc_frame->data, enc_frame->datalen, session->read_impl.actual_samples_per_second, session->enc_read_frame.data, &session->enc_read_frame.datalen, &session->enc_read_frame.rate, &flag); switch (status) { case SWITCH_STATUS_RESAMPLE: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fixme 1\n"); case SWITCH_STATUS_SUCCESS: session->enc_read_frame.samples = session->read_impl.decoded_bytes_per_packet / sizeof(int16_t); if (perfect) { if (enc_frame->codec->implementation->samples_per_packet != session->read_impl.samples_per_packet) { session->enc_read_frame.timestamp = 0; } else { session->enc_read_frame.timestamp = read_frame->timestamp; } session->enc_read_frame.rate = read_frame->rate; session->enc_read_frame.ssrc = read_frame->ssrc; session->enc_read_frame.seq = read_frame->seq; session->enc_read_frame.m = read_frame->m; session->enc_read_frame.payload = session->read_impl.ianacode; } *frame = &session->enc_read_frame; break; case SWITCH_STATUS_NOOP: session->raw_read_frame.samples = enc_frame->codec->implementation->samples_per_packet; session->raw_read_frame.timestamp = read_frame->timestamp; session->raw_read_frame.payload = enc_frame->codec->implementation->ianacode; session->raw_read_frame.m = read_frame->m; session->raw_read_frame.ssrc = read_frame->ssrc; session->raw_read_frame.seq = read_frame->seq; *frame = enc_frame; status = SWITCH_STATUS_SUCCESS; break; case SWITCH_STATUS_NOT_INITALIZED: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n"); *frame = NULL; status = SWITCH_STATUS_GENERR; break; default: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error!\n", session->read_codec->codec_interface->interface_name); *frame = NULL; status = SWITCH_STATUS_GENERR; break; } } else { goto top; } } } done: if (!(*frame)) { status = SWITCH_STATUS_FALSE; } else { if (flag & SFF_CNG) { switch_set_flag((*frame), SFF_CNG); } if (session->bugs) { switch_media_bug_t *bp; switch_bool_t ok = SWITCH_TRUE; int prune = 0; switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) { continue; } if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) { continue; } if (switch_test_flag(bp, SMBF_PRUNE)) { prune++; continue; } if (bp->ready && switch_test_flag(bp, SMBF_READ_PING)) { switch_mutex_lock(bp->read_mutex); if (bp->callback) { if (bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_PING) == SWITCH_FALSE || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) { ok = SWITCH_FALSE; } } switch_mutex_unlock(bp->read_mutex); } if (ok == SWITCH_FALSE) { switch_set_flag(bp, SMBF_PRUNE); prune++; } } switch_thread_rwlock_unlock(session->bug_rwlock); if (prune) { switch_core_media_bug_prune(session); } } } even_more_done: if (!*frame || !(*frame)->codec || !(*frame)->codec->implementation || !switch_core_codec_ready((*frame)->codec)) { *frame = &runtime.dummy_cng_frame; } switch_mutex_unlock(session->read_codec->mutex); switch_mutex_unlock(session->codec_read_mutex); return status; }
static switch_status_t my_on_reporting(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_status_t status = SWITCH_STATUS_SUCCESS; const char *log_dir = NULL, *accountcode = NULL, *a_template_str = NULL, *g_template_str = NULL; char *log_line, *path = NULL; if (globals.shutdown) { return SWITCH_STATUS_SUCCESS; } if (!((globals.legs & CDR_LEG_A) && (globals.legs & CDR_LEG_B))) { if ((globals.legs & CDR_LEG_A)) { if (switch_channel_get_originator_caller_profile(channel)) { return SWITCH_STATUS_SUCCESS; } } else { if (switch_channel_get_originatee_caller_profile(channel)) { return SWITCH_STATUS_SUCCESS; } } } if (!(log_dir = switch_channel_get_variable(channel, "cdr_csv_base"))) { log_dir = globals.log_dir; } if (switch_dir_make_recursive(log_dir, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", log_dir); return SWITCH_STATUS_FALSE; } if (globals.debug) { switch_event_t *event; if (switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { char *buf; switch_channel_event_set_data(channel, event); switch_event_serialize(event, &buf, SWITCH_FALSE); switch_assert(buf); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "CHANNEL_DATA:\n%s\n", buf); switch_event_destroy(&event); free(buf); } } g_template_str = (const char *) switch_core_hash_find(globals.template_hash, globals.default_template); if ((accountcode = switch_channel_get_variable(channel, "ACCOUNTCODE"))) { a_template_str = (const char *) switch_core_hash_find(globals.template_hash, accountcode); } if (!g_template_str) { g_template_str = "\"${accountcode}\",\"${caller_id_number}\",\"${destination_number}\",\"${context}\",\"${caller_id}\",\"${channel_name}\",\"${bridge_channel}\",\"${last_app}\",\"${last_arg}\",\"${start_stamp}\",\"${answer_stamp}\",\"${end_stamp}\",\"${duration}\",\"${billsec}\",\"${hangup_cause}\",\"${amaflags}\",\"${uuid}\",\"${userfield}\";"; } if (!a_template_str) { a_template_str = g_template_str; } log_line = switch_channel_expand_variables(channel, a_template_str); if ((accountcode) && (!globals.masterfileonly)) { path = switch_mprintf("%s%s%s.csv", log_dir, SWITCH_PATH_SEPARATOR, accountcode); assert(path); write_cdr(path, log_line); free(path); } if (g_template_str != a_template_str) { if (log_line != a_template_str) { switch_safe_free(log_line); } log_line = switch_channel_expand_variables(channel, g_template_str); } if (!log_line) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating cdr\n"); return SWITCH_STATUS_FALSE; } path = switch_mprintf("%s%sMaster.csv", log_dir, SWITCH_PATH_SEPARATOR); assert(path); write_cdr(path, log_line); free(path); if (log_line != g_template_str) { free(log_line); } return status; }
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t *session, const char *function, const char *target, switch_media_bug_callback_t callback, void *user_data, time_t stop_time, switch_media_bug_flag_t flags, switch_media_bug_t **new_bug) { switch_media_bug_t *bug, *bp; switch_size_t bytes; switch_event_t *event; int tap_only = 1, punt = 0; const char *p; if (!zstr(function)) { if ((flags & SMBF_ONE_ONLY)) { switch_thread_rwlock_wrlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (!zstr(bp->function) && !strcasecmp(function, bp->function)) { punt = 1; break; } } switch_thread_rwlock_unlock(session->bug_rwlock); } } if (punt) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n"); } if (!switch_channel_media_ready(session->channel)) { if (switch_channel_pre_answer(session->channel) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_FALSE; } } *new_bug = NULL; if ((p = switch_channel_get_variable(session->channel, "media_bug_answer_req")) && switch_true(p)) { flags |= SMBF_ANSWER_REQ; } #if 0 if (flags & SMBF_WRITE_REPLACE) { switch_thread_rwlock_wrlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (switch_test_flag(bp, SMBF_WRITE_REPLACE)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n"); switch_thread_rwlock_unlock(session->bug_rwlock); return SWITCH_STATUS_GENERR; } } switch_thread_rwlock_unlock(session->bug_rwlock); } if (flags & SMBF_READ_REPLACE) { switch_thread_rwlock_wrlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if (switch_test_flag(bp, SMBF_READ_REPLACE)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n"); switch_thread_rwlock_unlock(session->bug_rwlock); return SWITCH_STATUS_GENERR; } } switch_thread_rwlock_unlock(session->bug_rwlock); } #endif if (!(bug = switch_core_session_alloc(session, sizeof(*bug)))) { return SWITCH_STATUS_MEMERR; } bug->callback = callback; bug->user_data = user_data; bug->session = session; bug->flags = flags; bug->function = "N/A"; bug->target = "N/A"; switch_core_session_get_read_impl(session, &bug->read_impl); switch_core_session_get_write_impl(session, &bug->write_impl); if (function) { bug->function = switch_core_session_strdup(session, function); } if (target) { bug->target = switch_core_session_strdup(session, target); } bug->stop_time = stop_time; bytes = bug->read_impl.decoded_bytes_per_packet; if (!bug->flags) { bug->flags = (SMBF_READ_STREAM | SMBF_WRITE_STREAM); } if (switch_test_flag(bug, SMBF_READ_STREAM) || switch_test_flag(bug, SMBF_READ_PING)) { switch_buffer_create_dynamic(&bug->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER); switch_mutex_init(&bug->read_mutex, SWITCH_MUTEX_NESTED, session->pool); } bytes = bug->write_impl.decoded_bytes_per_packet; if (switch_test_flag(bug, SMBF_WRITE_STREAM)) { switch_buffer_create_dynamic(&bug->raw_write_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER); switch_mutex_init(&bug->write_mutex, SWITCH_MUTEX_NESTED, session->pool); } if ((bug->flags & SMBF_THREAD_LOCK)) { bug->thread_id = switch_thread_self(); } if (bug->callback) { switch_bool_t result = bug->callback(bug, bug->user_data, SWITCH_ABC_TYPE_INIT); if (result == SWITCH_FALSE) { switch_core_media_bug_destroy(bug); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error attaching BUG to %s\n", switch_channel_get_name(session->channel)); return SWITCH_STATUS_GENERR; } } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Attaching BUG to %s\n", switch_channel_get_name(session->channel)); bug->ready = 1; switch_thread_rwlock_wrlock(session->bug_rwlock); bug->next = session->bugs; session->bugs = bug; for(bp = session->bugs; bp; bp = bp->next) { if (bp->ready && !switch_test_flag(bp, SMBF_TAP_NATIVE_READ) && !switch_test_flag(bp, SMBF_TAP_NATIVE_WRITE)) { tap_only = 0; } } switch_thread_rwlock_unlock(session->bug_rwlock); *new_bug = bug; if (tap_only) { switch_set_flag(session, SSF_MEDIA_BUG_TAP_ONLY); } else { switch_clear_flag(session, SSF_MEDIA_BUG_TAP_ONLY); } if (switch_event_create(&event, SWITCH_EVENT_MEDIA_BUG_START) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Function", "%s", bug->function); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Media-Bug-Target", "%s", bug->target); switch_channel_event_set_data(session->channel, event); switch_event_fire(&event); } 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; }
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; }
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(void) switch_core_session_reporting_state(switch_core_session_t *session) { 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; int proceed = 1; int global_proceed = 1; int do_extra_handlers = 1; int silly = 0; int index = 0; const char *var = switch_channel_get_variable(session->channel, SWITCH_PROCESS_CDR_VARIABLE); const char *hook_var; int use_session = 0; switch_event_t *event; switch_call_cause_t cause = switch_channel_get_cause(session->channel); if (switch_channel_test_flag(session->channel, CF_REPORTING)) { return; } switch_channel_set_flag(session->channel, CF_REPORTING); switch_assert(session != NULL); endpoint_interface = session->endpoint_interface; switch_assert(endpoint_interface != NULL); driver_state_handler = endpoint_interface->state_handler; switch_assert(driver_state_handler != NULL); if (!zstr(var)) { if (!strcasecmp(var, "a_only")) { if (switch_channel_get_originator_caller_profile(session->channel)) { do_extra_handlers = 0; } } else if (!strcasecmp(var, "b_only")) { if (switch_channel_get_originatee_caller_profile(session->channel)) { do_extra_handlers = 0; } } else if (!switch_true(var)) { do_extra_handlers = 0; } } STATE_MACRO(reporting, "REPORTING"); if ((hook_var = switch_channel_get_variable(session->channel, SWITCH_API_REPORTING_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); } if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", switch_channel_cause2str(cause)); switch_channel_event_set_data(session->channel, event); switch_event_fire(&event); } return; }
SWITCH_DECLARE(void) switch_core_session_reporting_state(switch_core_session_t *session) { 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; int proceed = 1; int global_proceed = 1; int do_extra_handlers = 1; int silly = 0; int index = 0; const char *var = switch_channel_get_variable(session->channel, SWITCH_PROCESS_CDR_VARIABLE); const char *skip_var = switch_channel_get_variable(session->channel, SWITCH_SKIP_CDR_CAUSES_VARIABLE); const char *hook_var; int use_session = 0; switch_event_t *event; switch_call_cause_t cause = switch_channel_get_cause(session->channel); if (switch_channel_test_flag(session->channel, CF_REPORTING)) { return; } switch_channel_set_flag(session->channel, CF_REPORTING); switch_assert(session != NULL); endpoint_interface = session->endpoint_interface; switch_assert(endpoint_interface != NULL); driver_state_handler = endpoint_interface->state_handler; switch_assert(driver_state_handler != NULL); if (!zstr(var)) { if (!strcasecmp(var, "a_only")) { if (switch_channel_get_originator_caller_profile(session->channel)) { do_extra_handlers = 0; } } else if (!strcasecmp(var, "b_only")) { if (switch_channel_get_originatee_caller_profile(session->channel)) { do_extra_handlers = 0; } } else if (!switch_true(var)) { do_extra_handlers = 0; } } if (!zstr(skip_var)) { int x, ttl = 0; char *list[128] = { 0 }; char *dup = switch_core_session_strdup(session, skip_var); ttl = switch_split(dup, '|', list); for(x = 0; x < ttl; x++) { if (switch_channel_str2cause(list[x]) == cause) { do_extra_handlers = 0; break; } } } if (switch_channel_test_flag(session->channel, CF_NO_CDR)) { do_extra_handlers = 0; } STATE_MACRO(reporting, "REPORTING"); if ((hook_var = switch_channel_get_variable(session->channel, SWITCH_API_REPORTING_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); } if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", switch_channel_cause2str(cause)); switch_channel_event_set_data(session->channel, event); if (switch_true(switch_channel_get_variable(session->channel, "hangup_complete_with_xml"))) { switch_xml_t cdr = NULL; char *xml_cdr_text; if (switch_ivr_generate_xml_cdr(session, &cdr) == SWITCH_STATUS_SUCCESS) { xml_cdr_text = switch_xml_toxml(cdr, SWITCH_FALSE); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CDR-Attached", "xml"); switch_event_add_body(event, "%s", xml_cdr_text); switch_xml_free(cdr); switch_safe_free(xml_cdr_text); } } switch_event_fire(&event); } return; }
SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session) { switch_channel_state_t state = CS_NEW, midstate = CS_DESTROY, endstate; 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; int silly = 0; uint32_t new_loops = 500; /* Life of the channel. you have channel and pool in your session everywhere you go you use the session to malloc with switch_core_session_alloc(session, <size>) The endpoint module gets the first crack at implementing the state if it wants to, it can cancel the default behavior by returning SWITCH_STATUS_FALSE Next comes the channel's event handler table that can be set by an application which also can veto the next behavior in line by returning SWITCH_STATUS_FALSE Finally the default state behavior is called. */ switch_assert(session != NULL); switch_set_flag(session, SSF_THREAD_RUNNING); endpoint_interface = session->endpoint_interface; switch_assert(endpoint_interface != NULL); driver_state_handler = endpoint_interface->state_handler; switch_assert(driver_state_handler != NULL); switch_mutex_lock(session->mutex); while ((state = switch_channel_get_state(session->channel)) != CS_DESTROY) { if (switch_channel_test_flag(session->channel, CF_BLOCK_STATE)) { switch_channel_wait_for_flag(session->channel, CF_BLOCK_STATE, SWITCH_FALSE, 0, NULL); if ((state = switch_channel_get_state(session->channel)) == CS_DESTROY) { break; } } midstate = state; if (state != switch_channel_get_running_state(session->channel) || state >= CS_HANGUP) { int index = 0; int proceed = 1; int global_proceed = 1; int do_extra_handlers = 1; switch_io_event_hook_state_run_t *ptr; switch_status_t rstatus = SWITCH_STATUS_SUCCESS; switch_channel_set_running_state(session->channel, state); switch_channel_clear_flag(session->channel, CF_TRANSFER); switch_channel_clear_flag(session->channel, CF_REDIRECT); if (session->endpoint_interface->io_routines->state_run) { rstatus = session->endpoint_interface->io_routines->state_run(session); } if (rstatus == SWITCH_STATUS_SUCCESS) { for (ptr = session->event_hooks.state_run; ptr; ptr = ptr->next) { if ((rstatus = ptr->state_run(session)) != SWITCH_STATUS_SUCCESS) { break; } } } switch (state) { case CS_NEW: /* Just created, Waiting for first instructions */ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) State NEW\n", switch_channel_get_name(session->channel)); break; case CS_DESTROY: goto done; case CS_REPORTING: /* Call Detail */ { switch_core_session_reporting_state(session); switch_channel_set_state(session->channel, CS_DESTROY); } goto done; case CS_HANGUP: /* Deactivate and end the thread */ { switch_core_session_hangup_state(session, SWITCH_TRUE); switch_channel_set_state(session->channel, CS_REPORTING); } break; case CS_INIT: /* Basic setup tasks */ { switch_event_t *event; STATE_MACRO(init, "INIT"); if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_CREATE) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(session->channel, event); switch_event_fire(&event); } if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_ORIGINATE) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(session->channel, event); switch_event_fire(&event); } } } break; case CS_ROUTING: /* Look for a dialplan and find something to do */ STATE_MACRO(routing, "ROUTING"); break; case CS_RESET: /* Reset */ STATE_MACRO(reset, "RESET"); break; /* These other states are intended for prolonged durations so we do not signal lock for them */ case CS_EXECUTE: /* Execute an Operation */ STATE_MACRO(execute, "EXECUTE"); break; case CS_EXCHANGE_MEDIA: /* loop all data back to source */ STATE_MACRO(exchange_media, "EXCHANGE_MEDIA"); break; case CS_SOFT_EXECUTE: /* send/recieve data to/from another channel */ STATE_MACRO(soft_execute, "SOFT_EXECUTE"); break; case CS_PARK: /* wait in limbo */ STATE_MACRO(park, "PARK"); break; case CS_CONSUME_MEDIA: /* wait in limbo */ STATE_MACRO(consume_media, "CONSUME_MEDIA"); break; case CS_HIBERNATE: /* sleep */ STATE_MACRO(hibernate, "HIBERNATE"); break; case CS_NONE: abort(); break; } check_presence(session); if (midstate == CS_DESTROY) { break; } } endstate = switch_channel_get_state(session->channel); if (endstate == switch_channel_get_running_state(session->channel)) { if (endstate == CS_NEW) { switch_yield(20000); switch_ivr_parse_all_events(session); if (!--new_loops) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s %s Abandoned\n", session->uuid_str, switch_core_session_get_name(session)); switch_channel_set_flag(session->channel, CF_NO_CDR); switch_channel_hangup(session->channel, SWITCH_CAUSE_WRONG_CALL_STATE); } } else { switch_ivr_parse_all_events(session); switch_ivr_parse_all_events(session); if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) { switch_channel_state_thread_lock(session->channel); switch_channel_set_flag(session->channel, CF_THREAD_SLEEPING); if (switch_channel_get_state(session->channel) == switch_channel_get_running_state(session->channel)) { switch_ivr_parse_all_events(session); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s session thread sleep state: %s!\n", switch_channel_get_name(session->channel), switch_channel_state_name(switch_channel_get_running_state(session->channel))); switch_thread_cond_wait(session->cond, session->mutex); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s session thread wake state: %s!\n", switch_channel_get_name(session->channel), switch_channel_state_name(switch_channel_get_running_state(session->channel))); } switch_channel_clear_flag(session->channel, CF_THREAD_SLEEPING); switch_channel_state_thread_unlock(session->channel); } switch_ivr_parse_all_events(session); switch_ivr_parse_all_events(session); } } } done: switch_mutex_unlock(session->mutex); switch_clear_flag(session, SSF_THREAD_RUNNING); }
static switch_status_t my_on_reporting(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_status_t status = SWITCH_STATUS_SUCCESS; char *values = NULL, *tmp = NULL, *pq_var = NULL; const char *var = NULL; cdr_field_t *cdr_field = NULL; switch_size_t len, offset; if (globals.shutdown) { return SWITCH_STATUS_SUCCESS; } if (!((globals.legs & CDR_LEG_A) && (globals.legs & CDR_LEG_B))) { if ((globals.legs & CDR_LEG_A)) { if (switch_channel_get_originator_caller_profile(channel)) { return SWITCH_STATUS_SUCCESS; } } else { if (switch_channel_get_originatee_caller_profile(channel)) { return SWITCH_STATUS_SUCCESS; } } } if (switch_dir_make_recursive(globals.spool_dir, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.spool_dir); return SWITCH_STATUS_FALSE; } if (globals.debug) { switch_event_t *event; if (switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { char *buf; switch_channel_event_set_data(channel, event); switch_event_serialize(event, &buf, SWITCH_FALSE); switch_assert(buf); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "CHANNEL_DATA:\n%s\n", buf); switch_event_destroy(&event); switch_safe_free(buf); } } switch_zmalloc(values, 1); offset = 0; for (cdr_field = globals.db_schema->fields; cdr_field->var_name; cdr_field++) { if ((var = switch_channel_get_variable(channel, cdr_field->var_name))) { /* Allocate sufficient buffer for PQescapeString */ len = strlen(var); tmp = switch_core_session_alloc(session, len * 2 + 1); PQescapeString(tmp, var, len); var = tmp; } if (cdr_field->quote) { if ((cdr_field->not_null == SWITCH_FALSE) && zstr(var)) { pq_var = switch_mprintf("null,", var); } else { pq_var = switch_mprintf("'%s',", var); } } else { pq_var = switch_mprintf("%s,", var); } /* Resize values buffer to accomodate next var */ len = strlen(pq_var); tmp = realloc(values, offset + len); values = tmp; memcpy(values + offset, pq_var, len); switch_safe_free(pq_var); offset += len; } *(values + --offset) = '\0'; insert_cdr(values); switch_safe_free(values); return status; }