SWITCH_DECLARE(switch_status_t) switch_core_media_bug_enumerate(switch_core_session_t *session, switch_stream_handle_t *stream) { switch_media_bug_t *bp; stream->write_function(stream, "<media-bugs>\n"); if (session->bugs) { switch_thread_rwlock_rdlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { int thread_locked = (bp->thread_id && bp->thread_id == switch_thread_self()); stream->write_function(stream, " <media-bug>\n" " <function>%s</function>\n" " <target>%s</target>\n" " <thread-locked>%d</thread-locked>\n" " </media-bug>\n", bp->function, bp->target, thread_locked); } switch_thread_rwlock_unlock(session->bug_rwlock); } stream->write_function(stream, "</media-bugs>\n"); return SWITCH_STATUS_SUCCESS; }
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all_function(switch_core_session_t *session, const char *function) { switch_media_bug_t *bp; switch_status_t status = SWITCH_STATUS_FALSE; if (session->bugs) { switch_thread_rwlock_wrlock(session->bug_rwlock); for (bp = session->bugs; bp; bp = bp->next) { if ((bp->thread_id && bp->thread_id != switch_thread_self()) || switch_test_flag(bp, SMBF_LOCK)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "BUG is thread locked skipping.\n"); continue; } if (!zstr(function) && strcmp(bp->function, function)) { continue; } if (bp->callback) { bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_CLOSE); } switch_core_media_bug_destroy(bp); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Removing BUG from %s\n", switch_channel_get_name(session->channel)); } session->bugs = NULL; switch_thread_rwlock_unlock(session->bug_rwlock); status = SWITCH_STATUS_SUCCESS; } if (switch_core_codec_ready(&session->bug_codec)) { switch_core_codec_destroy(&session->bug_codec); } return status; }
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove(switch_core_session_t *session, switch_media_bug_t **bug) { switch_media_bug_t *bp = NULL, *last = NULL; switch_status_t status = SWITCH_STATUS_FALSE; switch_thread_rwlock_wrlock(session->bug_rwlock); if (session->bugs) { for (bp = session->bugs; bp; bp = bp->next) { if ((!bp->thread_id || bp->thread_id == switch_thread_self()) && bp->ready && bp == *bug) { if (last) { last->next = bp->next; } else { session->bugs = bp->next; } break; } last = bp; } } if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) { switch_core_codec_destroy(&session->bug_codec); } switch_thread_rwlock_unlock(session->bug_rwlock); if (bp) { status = switch_core_media_bug_close(&bp); } return status; }
SWITCH_DECLARE(switch_status_t) switch_core_port_allocator_request_port(switch_core_port_allocator_t *alloc, switch_port_t *port_ptr) { switch_port_t port = 0; switch_status_t status = SWITCH_STATUS_FALSE; int even = switch_test_flag(alloc, SPF_EVEN); int odd = switch_test_flag(alloc, SPF_ODD); switch_mutex_lock(alloc->mutex); srand((unsigned) ((unsigned) (intptr_t) port_ptr + (unsigned) (intptr_t) switch_thread_self() + switch_micro_time_now())); while (alloc->track_used < alloc->track_len) { uint32_t index; uint32_t tries = 0; /* randomly pick a port */ index = rand() % alloc->track_len; /* if it is used walk up the list to find a free one */ while (alloc->track[index] && tries < alloc->track_len) { tries++; if (alloc->track[index] < 0) { alloc->track[index]++; } if (++index >= alloc->track_len) { index = 0; } } if (tries < alloc->track_len) { alloc->track[index] = 1; alloc->track_used++; status = SWITCH_STATUS_SUCCESS; if ((even && odd)) { port = (switch_port_t) (index + alloc->start); } else { port = (switch_port_t) (index + (alloc->start / 2)); port *= 2; } goto end; } } end: switch_mutex_unlock(alloc->mutex); if (status == SWITCH_STATUS_SUCCESS) { *port_ptr = port; } else { *port_ptr = 0; } return status; }
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove(switch_core_session_t *session, switch_media_bug_t **bug) { switch_media_bug_t *bp = NULL, *bp2 = NULL, *last = NULL; switch_status_t status = SWITCH_STATUS_FALSE; int tap_only = 0; if (switch_core_media_bug_test_flag(*bug, SMBF_LOCK)) { return status; } switch_thread_rwlock_wrlock(session->bug_rwlock); if (session->bugs) { for (bp = session->bugs; bp; bp = bp->next) { if ((!bp->thread_id || bp->thread_id == switch_thread_self()) && bp->ready && bp == *bug) { if (last) { last->next = bp->next; } else { session->bugs = bp->next; } break; } last = bp; } } if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) { switch_core_codec_destroy(&session->bug_codec); } if (session->bugs) { for(bp2 = session->bugs; bp2; bp2 = bp2->next) { if (bp2->ready && !switch_test_flag(bp2, SMBF_TAP_NATIVE_READ) && !switch_test_flag(bp2, SMBF_TAP_NATIVE_WRITE)) { tap_only = 0; } } } if (tap_only) { switch_set_flag(session, SSF_MEDIA_BUG_TAP_ONLY); } else { switch_clear_flag(session, SSF_MEDIA_BUG_TAP_ONLY); } switch_thread_rwlock_unlock(session->bug_rwlock); if (bp) { status = switch_core_media_bug_close(&bp); } return status; }
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_close(switch_media_bug_t **bug) { switch_media_bug_t *bp = *bug; if (bp) { if ((bp->thread_id && bp->thread_id != switch_thread_self()) || switch_test_flag(bp, SMBF_LOCK)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(*bug)), SWITCH_LOG_DEBUG, "BUG is thread locked skipping.\n"); return SWITCH_STATUS_FALSE; } if (bp->callback) { bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_CLOSE); bp->ready = 0; } switch_core_media_bug_destroy(bp); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(*bug)), SWITCH_LOG_DEBUG, "Removing BUG from %s\n", switch_channel_get_name(bp->session->channel)); *bug = NULL; return SWITCH_STATUS_SUCCESS; } return SWITCH_STATUS_FALSE; }
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_callback(switch_core_session_t *session, switch_media_bug_callback_t callback) { switch_media_bug_t *cur = NULL, *bp = NULL, *last = NULL; int total = 0; switch_thread_rwlock_wrlock(session->bug_rwlock); if (session->bugs) { bp = session->bugs; while (bp) { cur = bp; bp = bp->next; if ((!cur->thread_id || cur->thread_id == switch_thread_self()) && cur->ready && cur->callback == callback) { if (last) { last->next = cur->next; } else { session->bugs = cur->next; } if (switch_core_media_bug_close(&cur) == SWITCH_STATUS_SUCCESS) { total++; } } else { last = cur; } } } if (!session->bugs && switch_core_codec_ready(&session->bug_codec)) { switch_core_codec_destroy(&session->bug_codec); } switch_thread_rwlock_unlock(session->bug_rwlock); return total ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; }
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(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 inline unsigned long switch_ssl_ssl_thread_id(void) { return (unsigned long) switch_thread_self(); }