struct switch_app_log *next;
};
+#define MESSAGE_STRING_ARG_MAX 10
/*! \brief A message object designed to allow unlike technologies to exchange data */
struct switch_core_session_message {
/*! uuid of the sender (for replies) */
const char *_file;
const char *_func;
int _line;
- const char *string_array_arg[10];
+ const char *string_array_arg[MESSAGE_STRING_ARG_MAX];
};
/*! \brief A generic object to pass as a thread's session object to allow mutiple arguements and a pool */
/*!
\brief Signal a session's state machine thread that a state change has occured
*/
+SWITCH_DECLARE(void) switch_core_session_wake_session_thread(_In_ switch_core_session_t *session);
SWITCH_DECLARE(void) switch_core_session_signal_state_change(_In_ switch_core_session_t *session);
/*!
SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_locate(const char *uuid_str, const char *file, const char *func, int line);
#endif
+#ifdef SWITCH_DEBUG_RWLOCKS
+SWITCH_DECLARE(switch_core_session_t *) switch_core_session_perform_force_locate(const char *uuid_str, const char *file, const char *func, int line);
+#endif
+
/*!
\brief Locate a session based on it's uuid
\param uuid_str the unique id of the session you want to find
*/
SWITCH_DECLARE(switch_status_t) switch_core_session_queue_message(_In_ switch_core_session_t *session, _In_ switch_core_session_message_t *message);
+SWITCH_DECLARE(void) switch_core_session_free_message(switch_core_session_message_t **message);
+
/*!
\brief pass an indication message on a session
\param session the session to pass the message across
*/
SWITCH_DECLARE(switch_status_t) switch_ivr_parse_all_events(switch_core_session_t *session);
SWITCH_DECLARE(switch_status_t) switch_ivr_parse_next_event(switch_core_session_t *session);
+SWITCH_DECLARE(switch_status_t) switch_ivr_parse_all_messages(switch_core_session_t *session);
/*!
\brief Wait for time to pass for a specified number of milliseconds
switch_channel_clear_app_flag(channel, CF_APP_TAGGED);
switch_set_flag_locked(member, MFLAG_FLUSH_BUFFER);
switch_core_session_set_read_codec(member->session, &member->read_codec);
+ } else {
+ switch_ivr_parse_all_messages(member->session);
}
if (use_timer) {
}
}
- switch_core_session_queue_indication(session, SWITCH_MESSAGE_INDICATE_RINGING);
switch_channel_mark_ring_ready(channel);
while (switch_channel_get_state(channel) == CS_INIT && !switch_test_flag(tech_pvt, TFLAG_ANSWER)) {
started = switch_micro_time_now();
/* jingle has no ringing indication so we will just pretend that we got one */
- switch_core_session_queue_indication(session, SWITCH_MESSAGE_INDICATE_RINGING);
switch_channel_mark_ring_ready(channel);
if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
break;
case IAX_EVENT_RINGA:
if (channel) {
- switch_core_session_queue_indication(tech_pvt->session, SWITCH_MESSAGE_INDICATE_RINGING);
switch_channel_mark_ring_ready(channel);
}
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_NOTICE, "Ringing heard.\n");
switch_mutex_unlock(globals.pvt_lock);
switch_yield(1000000);
} else {
- switch_core_session_queue_indication(session, SWITCH_MESSAGE_INDICATE_RINGING);
switch_channel_mark_ring_ready(channel);
}
}
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) && (session_b = switch_core_session_locate(uuid))) {
- switch_core_session_message_t msg = { 0 };
+ switch_core_session_message_t *msg;
- msg.message_id = SWITCH_MESSAGE_INDICATE_DISPLAY;
- msg.string_array_arg[0] = name;
- msg.string_array_arg[1] = number;
- msg.from = __FILE__;
- switch_core_session_receive_message(session_b, &msg);
+ msg = switch_core_session_alloc(session_b, sizeof(*msg));
+ msg->message_id = SWITCH_MESSAGE_INDICATE_DISPLAY;
+ msg->string_array_arg[0] = switch_core_session_strdup(session_b, name);
+ msg->string_array_arg[1] = switch_core_session_strdup(session_b, number);
+ msg->from = __FILE__;
+ switch_core_session_queue_message(session_b, msg);
switch_core_session_rwunlock(session_b);
}
}
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) && (other_session = switch_core_session_locate(uuid))) {
const char *r_sdp = NULL;
- switch_core_session_message_t msg = { 0 };
+ switch_core_session_message_t *msg;
if (sip->sip_payload && sip->sip_payload->pl_data &&
sip->sip_content_type && sip->sip_content_type->c_subtype && switch_stristr("sdp", sip->sip_content_type->c_subtype)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing %d %s to other leg\n", status, phrase);
- msg.message_id = SWITCH_MESSAGE_INDICATE_RESPOND;
- msg.from = __FILE__;
- msg.numeric_arg = status;
- msg.string_arg = switch_core_session_strdup(other_session, phrase);
+ msg = switch_core_session_alloc(other_session, sizeof(*msg));
+ msg->message_id = SWITCH_MESSAGE_INDICATE_RESPOND;
+ msg->from = __FILE__;
+ msg->numeric_arg = status;
+ msg->string_arg = switch_core_session_strdup(other_session, phrase);
if (r_sdp) {
- msg.pointer_arg = switch_core_session_strdup(other_session, r_sdp);
- msg.pointer_arg_size = strlen(r_sdp);
+ msg->pointer_arg = switch_core_session_strdup(other_session, r_sdp);
+ msg->pointer_arg_size = strlen(r_sdp);
}
- switch_mutex_unlock(tech_pvt->sofia_mutex);
- status = switch_core_session_receive_message(other_session, &msg);
- switch_mutex_lock(tech_pvt->sofia_mutex);
-
- if (status != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Other leg is not available\n");
- nua_respond(tech_pvt->nh, 403, "Hangup in progress", TAG_END());
- }
+ switch_core_session_queue_message(other_session, msg);
switch_core_session_rwunlock(other_session);
}
return;
case nua_callstate_proceeding:
if (status == 180) {
switch_channel_mark_ring_ready(channel);
- if (!switch_channel_test_flag(channel, CF_GEN_RINGBACK)) {
- if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
- if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))
- && (other_session = switch_core_session_locate(uuid))) {
- switch_core_session_message_t msg;
- msg.message_id = SWITCH_MESSAGE_INDICATE_RINGING;
- msg.from = __FILE__;
- switch_mutex_unlock(tech_pvt->sofia_mutex);
- switch_core_session_receive_message(other_session, &msg);
- switch_mutex_lock(tech_pvt->sofia_mutex);
- switch_core_session_rwunlock(other_session);
- }
-
- } else {
- switch_core_session_queue_indication(session, SWITCH_MESSAGE_INDICATE_RINGING);
- }
- }
}
if (r_sdp) {
goto done;
}
}
- if (!switch_channel_test_flag(channel, CF_GEN_RINGBACK) && (uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))
+ if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))
&& (other_session = switch_core_session_locate(uuid))) {
other_channel = switch_core_session_get_channel(other_session);
if (!switch_channel_get_variable(other_channel, SWITCH_B_SDP_VARIABLE)) {
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))
&& (other_session = switch_core_session_locate(uuid))) {
- switch_core_session_message_t msg = { 0 };
+ switch_core_session_message_t *msg;
if (profile->media_options & MEDIA_OPT_MEDIA_ON_HOLD) {
tech_pvt->hold_laps = 1;
goto done;
}
- msg.message_id = SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT;
- msg.from = __FILE__;
- msg.string_arg = (char *) r_sdp;
+ msg = switch_core_session_alloc(other_session, sizeof(*msg));
+ msg->message_id = SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT;
+ msg->from = __FILE__;
+ msg->string_arg = switch_core_session_strdup(other_session, r_sdp);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing SDP to other leg.\n%s\n", r_sdp);
if (sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
switch_channel_presence(tech_pvt->channel, "unknown", "hold", NULL);
}
- switch_mutex_unlock(tech_pvt->sofia_mutex);
- status = switch_core_session_receive_message(other_session, &msg);
- switch_mutex_lock(tech_pvt->sofia_mutex);
+ switch_core_session_queue_message(other_session, msg);
- if (status != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Other leg is not available\n");
- nua_respond(tech_pvt->nh, 403, "Hangup in progress", TAG_END());
- }
switch_core_session_rwunlock(other_session);
} else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Re-INVITE to a no-media channel that is not in a bridge.\n");
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
+ "Re-INVITE to a no-media channel that is not in a bridge.\n");
is_ok = 0;
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
SWITCH_DECLARE(void) switch_channel_audio_sync(switch_channel_t *channel)
{
if (switch_channel_media_ready(channel)) {
- switch_core_session_message_t msg;
+ switch_core_session_message_t msg = { 0 };
msg.message_id = SWITCH_MESSAGE_INDICATE_AUDIO_SYNC;
msg.from = channel->name;
switch_core_session_receive_message(channel->session, &msg);
SWITCH_DECLARE(switch_status_t) switch_channel_perform_pre_answer(switch_channel_t *channel, const char *file, const char *func, int line)
{
- switch_core_session_message_t msg;
+ switch_core_session_message_t msg = { 0 };
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_assert(channel != NULL);
SWITCH_DECLARE(switch_status_t) switch_channel_perform_ring_ready(switch_channel_t *channel, const char *file, const char *func, int line)
{
- switch_core_session_message_t msg;
+ switch_core_session_message_t msg = { 0 };
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_assert(channel != NULL);
SWITCH_DECLARE(switch_status_t) switch_channel_perform_answer(switch_channel_t *channel, const char *file, const char *func, int line)
{
- switch_core_session_message_t msg;
+ switch_core_session_message_t msg = { 0 };
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_assert(channel != NULL);
break;
}
+ switch_core_session_free_message(&message);
switch_core_session_rwunlock(session);
return status;
if (switch_queue_trypush(session->message_queue, message) == SWITCH_STATUS_SUCCESS) {
status = SWITCH_STATUS_SUCCESS;
}
+
+ if (switch_channel_test_flag(session->channel, CF_PROXY_MODE)) {
+ switch_core_session_wake_session_thread(session);
+ }
}
return status;
}
+SWITCH_DECLARE(void) switch_core_session_free_message(switch_core_session_message_t **message)
+{
+ switch_core_session_message_t *to_free = *message;
+ int i;
+ char *s;
+
+ *message = NULL;
+
+ if (switch_test_flag(to_free, SCSMF_DYNAMIC)) {
+ s = (char *)to_free->string_arg;
+ switch_safe_free(s);
+ switch_safe_free(to_free->pointer_arg);
+
+ for (i = 0; i < MESSAGE_STRING_ARG_MAX; i++) {
+ s = (char *)to_free->string_array_arg[i];
+ switch_safe_free(s);
+ }
+
+ switch_safe_free(to_free);
+ }
+}
+
SWITCH_DECLARE(switch_status_t) switch_core_session_dequeue_message(switch_core_session_t *session, switch_core_session_message_t **message)
{
switch_status_t status = SWITCH_STATUS_FALSE;
{
switch_core_session_message_t *message;
- if (switch_core_session_dequeue_message(session, &message) == SWITCH_STATUS_SUCCESS) {
- if (switch_test_flag(message, SCSMF_DYNAMIC)) {
- switch_safe_free(message);
- } else {
- message = NULL;
- }
+ while (switch_core_session_dequeue_message(session, &message) == SWITCH_STATUS_SUCCESS) {
+ switch_core_session_free_message(&message);
}
return SWITCH_STATUS_SUCCESS;
return session->channel;
}
-SWITCH_DECLARE(void) switch_core_session_signal_state_change(switch_core_session_t *session)
+SWITCH_DECLARE(void) switch_core_session_wake_session_thread(switch_core_session_t *session)
{
- switch_status_t status = SWITCH_STATUS_SUCCESS;
- switch_io_event_hook_state_change_t *ptr;
-
/* If trylock fails the signal is already awake so we needn't bother */
if (switch_mutex_trylock(session->mutex) == SWITCH_STATUS_SUCCESS) {
switch_thread_cond_signal(session->cond);
switch_mutex_unlock(session->mutex);
}
+}
+
+SWITCH_DECLARE(void) switch_core_session_signal_state_change(switch_core_session_t *session)
+{
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_io_event_hook_state_change_t *ptr;
+
+ switch_core_session_wake_session_thread(session);
if (session->endpoint_interface->io_routines->state_change) {
status = session->endpoint_interface->io_routines->state_change(session);
switch_channel_hangup(session->channel, SWITCH_CAUSE_INVALID_CALL_REFERENCE);
}
} else {
+ switch_core_session_message_t *message;
+
+ while (switch_core_session_dequeue_message(session, &message) == SWITCH_STATUS_SUCCESS) {
+ switch_core_session_receive_message(session, message);
+ message = NULL;
+ }
+
switch_thread_cond_wait(session->cond, session->mutex);
+
+ while (switch_core_session_dequeue_message(session, &message) == SWITCH_STATUS_SUCCESS) {
+ switch_core_session_receive_message(session, message);
+ message = NULL;
+ }
}
}
}
break;
}
- if (switch_core_session_private_event_count(session)) {
- switch_ivr_parse_all_events(session);
- }
+
+ switch_ivr_parse_all_events(session);
+
if (args && (args->input_callback || args->buf || args->buflen)) {
switch_dtmf_t dtmf;
}
+SWITCH_DECLARE(switch_status_t) switch_ivr_parse_all_messages(switch_core_session_t *session)
+{
+ switch_core_session_message_t *message;
+ int i = 0;
+
+ while (switch_core_session_dequeue_message(session, &message) == SWITCH_STATUS_SUCCESS) {
+ i++;
+ switch_core_session_receive_message(session, message);
+ message = NULL;
+ }
+
+ return i ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
+}
+
SWITCH_DECLARE(switch_status_t) switch_ivr_parse_all_events(switch_core_session_t *session)
{
+
while (switch_ivr_parse_next_event(session) == SWITCH_STATUS_SUCCESS);
+ switch_ivr_parse_all_messages(session);
switch_ivr_sleep(session, 0, SWITCH_TRUE, NULL);
return SWITCH_STATUS_SUCCESS;
}
}
- if (switch_core_session_private_event_count(session)) {
- switch_ivr_parse_all_events(session);
- }
+ switch_ivr_parse_all_events(session);
+
if (switch_channel_has_dtmf(channel)) {
switch_dtmf_t dtmf = { 0 };
}
}
- if (switch_core_session_private_event_count(session)) {
- switch_ivr_parse_all_events(session);
- }
+
+ switch_ivr_parse_all_events(session);
+
if (switch_channel_has_dtmf(channel)) {
switch_channel_dequeue_dtmf(channel, &dtmf);
}
}
- if (switch_core_session_private_event_count(session)) {
- switch_ivr_parse_all_events(session);
- }
+
+ switch_ivr_parse_all_events(session);
+
if (eff_timeout) {
break;
}
- if (switch_core_session_private_event_count(session)) {
- switch_ivr_parse_all_events(session);
- }
+ switch_ivr_parse_all_events(session);
if (args && (args->input_callback || args->buf || args->buflen)) {
switch_dtmf_t dtmf;
if (switch_core_session_dequeue_message(session_b, &message) == SWITCH_STATUS_SUCCESS) {
switch_core_session_receive_message(session_a, message);
- if (switch_test_flag(message, SCSMF_DYNAMIC)) {
- switch_safe_free(message);
- } else {
- message = NULL;
- }
+ message = NULL;
}
if (!ans_a && answer_limit && switch_epoch_time_now(NULL) > answer_limit) {
if (!oglobals->ring_ready) {
oglobals->ring_ready = 1;
+ if (caller_channel && !oglobals->ignore_ring_ready) {
+ switch_channel_ring_ready(caller_channel);
+ }
}
}
if (!oglobals->ring_ready && !oglobals->ignore_ring_ready) {
oglobals->ring_ready = 1;
+
}
}
}
- if (switch_core_session_private_event_count(originate_status[i].peer_session)) {
- switch_ivr_parse_all_events(originate_status[i].peer_session);
- }
+ switch_ivr_parse_all_events(originate_status[i].peer_session);
state = switch_channel_get_state(originate_status[i].peer_channel);
if (state >= CS_HANGUP || state == CS_RESET || switch_channel_test_flag(originate_status[i].peer_channel, CF_TRANSFER) ||
switch_codec_t *read_codec = switch_core_session_get_read_codec(session);
uint8_t pass = 0;
ringback_t ringback = { 0 };
- switch_core_session_message_t *message = NULL;
switch_frame_t *read_frame = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
int timelimit = 60;
goto done;
}
-
- if (switch_core_session_dequeue_message(peer_session, &message) == SWITCH_STATUS_SUCCESS) {
- if (switch_test_flag(message, SCSMF_DYNAMIC)) {
- switch_safe_free(message);
- } else {
- message = NULL;
- }
- }
-
if (switch_channel_media_ready(caller_channel)) {
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (!SWITCH_READ_ACCEPTABLE(status)) {
check_per_channel_timeouts(&oglobals, originate_status, and_argc, start);
- if (oglobals.session && switch_core_session_private_event_count(oglobals.session)) {
+ if (oglobals.session) {
switch_ivr_parse_all_events(oglobals.session);
}
}
if (originate_status[0].peer_session
- && switch_core_session_dequeue_message(originate_status[0].peer_session, &message) == SWITCH_STATUS_SUCCESS) {
+ && switch_core_session_dequeue_message(oglobals.session, &message) == SWITCH_STATUS_SUCCESS) {
if (oglobals.session && !ringback_data && or_argc == 1 && and_argc == 1) {
/* when there is only 1 channel to call and bridge and no ringback */
switch_core_session_receive_message(oglobals.session, message);
}
-
- if (switch_test_flag(message, SCSMF_DYNAMIC)) {
- switch_safe_free(message);
- } else {
- message = NULL;
- }
+ message = NULL;
}
/* read from the channel while we wait if the audio is up on it */
break;
}
- if (switch_core_session_private_event_count(session)) {
- switch_ivr_parse_all_events(session);
- }
+ switch_ivr_parse_all_events(session);
if (start && (switch_epoch_time_now(NULL) - start) > limit) {
break;
break;
}
- if (switch_core_session_private_event_count(session)) {
- switch_ivr_parse_all_events(session);
- }
+ switch_ivr_parse_all_events(session);
if (args && (args->input_callback || args->buf || args->buflen)) {
/*
break;
}
- if (switch_core_session_private_event_count(session)) {
- switch_ivr_parse_all_events(session);
- }
+ switch_ivr_parse_all_events(session);
if (args && (args->input_callback || args->buf || args->buflen)) {
/*