diff --git a/src/include/switch_types.h b/src/include/switch_types.h index dde5b51fbe..5f21cd411a 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -955,6 +955,7 @@ typedef enum { CF_LEG_HOLDING, CF_BROADCAST_DROP_MEDIA, CF_EARLY_HANGUP, + CF_MEDIA_SET, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ CF_FLAG_MAX } switch_channel_flag_t; diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index fdd767f614..8db4330c01 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1410,7 +1410,6 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi if (!(switch_channel_test_flag(channel, CF_ANSWERED) || switch_channel_test_flag(channel, CF_EARLY_MEDIA))) { if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) { const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE); - tech_pvt->num_codecs = 0; sofia_glue_tech_prepare_codecs(tech_pvt); if (sofia_glue_tech_media(tech_pvt, r_sdp) != SWITCH_STATUS_SUCCESS) { diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 0b0571f77e..e205c4619a 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4300,6 +4300,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, if (sofia_glue_tech_media(tech_pvt, r_sdp) != SWITCH_STATUS_SUCCESS) { switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR"); status = SWITCH_STATUS_FALSE; + switch_core_session_rwunlock(other_session); goto done; } } @@ -4309,6 +4310,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, sofia_glue_tech_prepare_codecs(tech_pvt); if ((status = sofia_glue_tech_choose_port(tech_pvt, 0)) != SWITCH_STATUS_SUCCESS) { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + switch_core_session_rwunlock(other_session); goto done; } } @@ -4715,8 +4717,9 @@ void *SWITCH_THREAD_FUNC nightmare_xfer_thread_run(switch_thread_t *thread, void nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("messsage/sipfrag"), NUTAG_SUBSTATE(nua_substate_terminated), - SIPTAG_PAYLOAD_STR(status == SWITCH_STATUS_SUCCESS ? "SIP/2.0 200 OK": - "SIP/2.0 403 Forbidden"), SIPTAG_EVENT_STR(nhelper->event), TAG_END()); + SIPTAG_HEADER_STR(status == SWITCH_STATUS_SUCCESS ? "Status-Line: SIP/2.0 200 OK\n" : "Status-Line: SIP/2.0 403 Forbidden\n"), + SIPTAG_PAYLOAD_STR(status == SWITCH_STATUS_SUCCESS ? "SIP/2.0 200 OK\r\n": + "SIP/2.0 403 Forbidden\r\n"), SIPTAG_EVENT_STR(nhelper->event), TAG_END()); switch_core_session_rwunlock(session); } @@ -4962,8 +4965,8 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t switch_core_session_rwunlock(a_session); - nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), - NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK"), SIPTAG_EVENT_STR(etmp), TAG_END()); + nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"), + NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK\r\n"), SIPTAG_EVENT_STR(etmp), TAG_END()); if (b_tech_pvt && !sofia_test_flag(b_tech_pvt, TFLAG_BYE)) { char* q850 = NULL; @@ -4981,9 +4984,9 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t } } else { - nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), + nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"), NUTAG_SUBSTATE(nua_substate_terminated), - SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden"), SIPTAG_EVENT_STR(etmp), TAG_END()); + SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden\r\n"), SIPTAG_EVENT_STR(etmp), TAG_END()); } } else if (br_a && br_b) { @@ -5001,8 +5004,8 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t switch_ivr_uuid_bridge(br_b, br_a); switch_channel_set_variable(channel_b, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER"); - nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), - NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK"), SIPTAG_EVENT_STR(etmp), TAG_END()); + nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"), + NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK\r\n"), SIPTAG_EVENT_STR(etmp), TAG_END()); sofia_clear_flag_locked(b_tech_pvt, TFLAG_SIP_HOLD); switch_channel_clear_flag(channel_b, CF_LEG_HOLDING); @@ -5013,9 +5016,9 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t } else { if (!br_a && !br_b) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot transfer channels that are not in a bridge.\n"); - nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), + nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"), NUTAG_SUBSTATE(nua_substate_terminated), - SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden"), SIPTAG_EVENT_STR(etmp), TAG_END()); + SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden\r\n"), SIPTAG_EVENT_STR(etmp), TAG_END()); } else { switch_core_session_t *t_session; switch_channel_t *hup_channel; @@ -5056,16 +5059,16 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), - SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), + SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"), NUTAG_SUBSTATE(nua_substate_terminated), - SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK"), SIPTAG_EVENT_STR(etmp), TAG_END()); + SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK\r\n"), SIPTAG_EVENT_STR(etmp), TAG_END()); switch_core_session_rwunlock(t_session); switch_channel_hangup(hup_channel, SWITCH_CAUSE_ATTENDED_TRANSFER); } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session to transfer to not found.\n"); - nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), + nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"), NUTAG_SUBSTATE(nua_substate_terminated), - SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden"), SIPTAG_EVENT_STR(etmp), TAG_END()); + SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden\r\n"), SIPTAG_EVENT_STR(etmp), TAG_END()); } } } @@ -5150,8 +5153,8 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t error: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Transfer! [%s]\n", br_a); switch_channel_set_variable(channel_a, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER_ERROR"); - nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), - NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden"), SIPTAG_EVENT_STR(etmp), + nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"), + NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden\r\n"), SIPTAG_EVENT_STR(etmp), TAG_END()); } } @@ -5188,14 +5191,14 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t } switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "BLIND_TRANSFER"); - nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), - NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK"), SIPTAG_EVENT_STR(etmp), TAG_END()); + nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"), + NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK\r\n"), SIPTAG_EVENT_STR(etmp), TAG_END()); } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot Blind Transfer 1 Legged calls\n"); switch_channel_set_variable(channel_a, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER_ERROR"); - nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), - NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden"), SIPTAG_EVENT_STR(etmp), TAG_END()); + nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"), + NUTAG_SUBSTATE(nua_substate_terminated), SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden\r\n"), SIPTAG_EVENT_STR(etmp), TAG_END()); } } @@ -6441,7 +6444,7 @@ void sofia_info_send_sipfrag(switch_core_session_t *aleg, switch_core_session_t snprintf(message, sizeof(message), "From:\r\nTo: \"%s\" %s\r\n", acp->caller_id_name, acp->caller_id_number); } nua_info(b_tech_pvt->nh, - SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), + SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"), TAG_IF(!zstr(b_tech_pvt->user_via), SIPTAG_VIA_STR(b_tech_pvt->user_via)), SIPTAG_PAYLOAD_STR(message), TAG_END()); } else if (ua && switch_stristr("polycom", ua)) { diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index d963527db7..724e193565 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -1459,6 +1459,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) max_forwards = switch_channel_get_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE); if ((status = sofia_glue_tech_choose_port(tech_pvt, 0)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Port Error!\n"); return status; } @@ -1803,6 +1804,8 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) tech_pvt->route_uri = switch_core_session_strdup(tech_pvt->session, route_uri); } + switch_channel_clear_flag(channel, CF_MEDIA_ACK); + if (sofia_use_soa(tech_pvt)) { nua_invite(tech_pvt->nh, NUTAG_AUTOANSWER(0), @@ -2201,6 +2204,7 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force) switch_core_session_unlock_codec_read(tech_pvt->session); } + return status; } diff --git a/src/switch_core_codec.c b/src/switch_core_codec.c index b17dcd28fa..4720fae509 100644 --- a/src/switch_core_codec.c +++ b/src/switch_core_codec.c @@ -167,6 +167,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_set_read_codec(switch_core_s end: + if (session->read_codec) { + switch_channel_set_flag(channel, CF_MEDIA_SET); + } + switch_mutex_unlock(session->codec_read_mutex); return status; diff --git a/src/switch_core_rwlock.c b/src/switch_core_rwlock.c index 2069a96c08..2fc31d970a 100644 --- a/src/switch_core_rwlock.c +++ b/src/switch_core_rwlock.c @@ -47,6 +47,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_lock(switch_core_sessio if (session->rwlock) { if (switch_test_flag(session, SSF_DESTROYED) || switch_channel_down(session->channel)) { status = SWITCH_STATUS_FALSE; + if (switch_thread_rwlock_tryrdlock(session->rwlock) == SWITCH_STATUS_SUCCESS) { + if (switch_channel_test_flag(session->channel, CF_THREAD_SLEEPING)) { +#ifdef SWITCH_DEBUG_RWLOCKS + switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_core_session_get_uuid(session), SWITCH_LOG_ERROR, "%s Ping thread\n", + switch_channel_get_name(session->channel)); +#endif + switch_core_session_wake_session_thread(session); + } + switch_thread_rwlock_unlock(session->rwlock); + } #ifdef SWITCH_DEBUG_RWLOCKS switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_core_session_get_uuid(session), SWITCH_LOG_ERROR, "%s Read lock FAIL\n", switch_channel_get_name(session->channel)); diff --git a/src/switch_ivr.c b/src/switch_ivr.c index ff124f0792..c87c0acbdf 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -1202,8 +1202,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_media(const char *uuid, switch_media_ switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 250, NULL); switch_yield(250000); } else { + switch_status_t st; switch_channel_wait_for_flag(channel, CF_REQ_MEDIA, SWITCH_FALSE, 10000, NULL); - switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); + switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL); + switch_channel_wait_for_flag(channel, CF_MEDIA_SET, SWITCH_TRUE, 10000, NULL); + st = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); } if ((flags & SMF_REBRIDGE) diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index a090551503..8ae98d4cb7 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -33,6 +33,8 @@ #define DEFAULT_LEAD_FRAMES 5 static const switch_state_handler_table_t audio_bridge_peer_state_handlers; +static void cleanup_proxy_mode_a(switch_core_session_t *session); +static void cleanup_proxy_mode_b(switch_core_session_t *session); /* Bridge Related Stuff*/ /*********************************************************************************/ @@ -693,6 +695,8 @@ static switch_status_t uuid_bridge_on_reset(switch_core_session_t *session) switch_channel_clear_flag(channel, CF_ORIGINATING); + cleanup_proxy_mode_b(session); + if (switch_channel_test_flag(channel, CF_BRIDGE_ORIGINATOR)) { switch_channel_set_state(channel, CS_SOFT_EXECUTE); } @@ -780,7 +784,8 @@ static switch_status_t uuid_bridge_on_soft_execute(switch_core_session_t *sessio switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application-Data", switch_core_session_get_uuid(session)); switch_event_fire(&event); } - + printf("DAMMIT %d %d %d %d\n", switch_channel_ready(channel), switch_channel_ready(other_channel), + switch_channel_media_ready(channel), switch_channel_media_ready(other_channel)); switch_ivr_multi_threaded_bridge(session, other_session, NULL, NULL, NULL); state = switch_channel_get_state(channel); @@ -1197,7 +1202,18 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses return status; } -static void cleanup_proxy_mode(switch_core_session_t *session) +static void cleanup_proxy_mode_b(switch_core_session_t *session) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + + + if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { + switch_ivr_media(switch_core_session_get_uuid(session), SMF_NONE); + } +} + + +static void cleanup_proxy_mode_a(switch_core_session_t *session) { switch_core_session_t *sbsession; @@ -1206,10 +1222,6 @@ static void cleanup_proxy_mode(switch_core_session_t *session) if (switch_channel_test_flag(channel, CF_PROXY_MODE)) { const char *sbv = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Restore media to %s\n", switch_channel_get_name(channel)); - switch_ivr_media(switch_core_session_get_uuid(session), SMF_IMMEDIATE); - if (!zstr(sbv) && (sbsession = switch_core_session_locate(sbv))) { switch_channel_t *sbchannel = switch_core_session_get_channel(sbsession); switch_channel_hangup(sbchannel, SWITCH_CAUSE_ATTENDED_TRANSFER); @@ -1262,8 +1274,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_uuid_bridge(const char *originator_uu } } - cleanup_proxy_mode(originator_session); - cleanup_proxy_mode(originatee_session); + cleanup_proxy_mode_a(originator_session); + cleanup_proxy_mode_a(originatee_session); /* override transmit state for originator_channel to bridge to originatee_channel * install pointer to originatee_session into originator_channel diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 736726cc6a..d3691e365c 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -2988,7 +2988,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess switch_channel_set_variable(switch_core_session_get_channel(holding_session), SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "true"); switch_core_session_rwunlock(holding_session); } - switch_ivr_uuid_bridge(holding, switch_core_session_get_uuid(peer_session)); holding = NULL; oglobals.idx = IDX_NADA; @@ -3055,7 +3054,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess switch_channel_set_variable(switch_core_session_get_channel(holding_session), SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "true"); switch_core_session_rwunlock(holding_session); } - switch_ivr_uuid_bridge(holding, switch_core_session_get_uuid(originate_status[i].peer_session)); holding = NULL; } else {