diff --git a/src/include/switch_core_media.h b/src/include/switch_core_media.h index 6e4c44af2f..e8cec64927 100644 --- a/src/include/switch_core_media.h +++ b/src/include/switch_core_media.h @@ -213,6 +213,7 @@ SWITCH_DECLARE(void) switch_core_media_pass_zrtp_hash(switch_core_session_t *ses SWITCH_DECLARE(const char *) switch_core_media_get_zrtp_hash(switch_core_session_t *session, switch_media_type_t type, switch_bool_t local); SWITCH_DECLARE(void) switch_core_media_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session); SWITCH_DECLARE(int) switch_core_media_toggle_hold(switch_core_session_t *session, int sendonly); +SWITCH_DECLARE(void) switch_core_media_reset_t38(switch_core_session_t *session); SWITCH_DECLARE(void) switch_core_media_copy_t38_options(switch_t38_options_t *t38_options, switch_core_session_t *session); SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *session, const char *r_sdp, uint8_t *proceed, switch_sdp_type_t sdp_type); SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_session_t *session, int force); diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 78f4f0d557..6fe594f9f7 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1537,7 +1537,8 @@ typedef enum { CF_APP_T38 = (1 << 1), CF_APP_T38_REQ = (1 << 2), CF_APP_T38_FAIL = (1 << 3), - CF_APP_T38_NEGOTIATED = (1 << 4) + CF_APP_T38_NEGOTIATED = (1 << 4), + CF_APP_T38_POSSIBLE = (1 << 5) } switch_channel_app_flag_t; diff --git a/src/mod/applications/mod_spandsp/mod_spandsp.c b/src/mod/applications/mod_spandsp/mod_spandsp.c index fdbb44c5a6..4e4319bfb8 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp.c +++ b/src/mod/applications/mod_spandsp/mod_spandsp.c @@ -221,6 +221,8 @@ SWITCH_STANDARD_APP(t38_gateway_function) } } + switch_channel_set_app_flag_key("T38", channel, CF_APP_T38_POSSIBLE); + if (zstr(direction) || strcasecmp(direction, "self")) { direction = "peer"; } diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c index 3d175a18e5..81dabb3f44 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c +++ b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c @@ -1354,7 +1354,12 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat counter_increment(); - + if (app_mode == FUNCTION_GW || + switch_channel_var_true(channel, "fax_enable_t38") || + switch_channel_var_true(channel, "fax_enable_t38_insist")) { + switch_channel_set_app_flag_key("T38", channel, CF_APP_T38_POSSIBLE); + } + pvt = pvt_init(session, app_mode); switch_channel_set_private(channel, "_fax_pvt", pvt); @@ -1599,6 +1604,8 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat /* Destroy the SpanDSP structures */ spanfax_destroy(pvt); + switch_channel_clear_app_flag_key("T38", channel, CF_APP_T38_POSSIBLE); + /* restore the original codecs over the channel */ switch_core_session_set_read_codec(session, NULL); @@ -2071,6 +2078,9 @@ switch_bool_t t38_gateway_start(switch_core_session_t *session, const char *app, switch_channel_set_app_flag_key("T38", peer ? channel : other_channel, CF_APP_TAGGED); switch_channel_clear_app_flag_key("T38", peer ? other_channel : channel, CF_APP_TAGGED); + switch_channel_set_app_flag_key("T38", channel, CF_APP_T38_POSSIBLE); + switch_channel_set_app_flag_key("T38", other_channel, CF_APP_T38_POSSIBLE); + switch_channel_set_flag(channel, CF_REDIRECT); switch_channel_set_state(channel, CS_RESET); @@ -2268,6 +2278,7 @@ switch_status_t spandsp_fax_detect_session(switch_core_session_t *session, switch_codec_implementation_t read_impl = { 0 }; switch_core_session_get_read_impl(session, &read_impl); + if (timeout) { to = switch_epoch_time_now(NULL) + timeout; } @@ -2281,6 +2292,8 @@ switch_status_t spandsp_fax_detect_session(switch_core_session_t *session, return SWITCH_STATUS_MEMERR; } + switch_channel_set_app_flag_key("T38", channel, CF_APP_T38_POSSIBLE); + if (app) { cont->app = switch_core_session_strdup(session, app); } diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index ba6ef2a929..73b2a384b1 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -6585,7 +6585,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status const char *r_sdp = NULL; switch_core_session_message_t *msg; private_object_t *other_tech_pvt = switch_core_session_get_private(other_session); - switch_channel_t *other_channel = switch_core_session_get_channel(other_session); + //switch_channel_t *other_channel = switch_core_session_get_channel(other_session); 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)) { @@ -6614,13 +6614,8 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status switch_core_session_rwunlock(other_session); goto end; } else if (status > 299) { - switch_channel_set_private(channel, "t38_options", NULL); - switch_channel_set_private(other_channel, "t38_options", NULL); - switch_channel_clear_flag(channel, CF_T38_PASSTHRU); - switch_channel_clear_flag(other_channel, CF_T38_PASSTHRU); - switch_channel_clear_app_flag_key("T38", channel, CF_APP_T38); - switch_channel_clear_app_flag_key("T38", channel, CF_APP_T38_REQ); - switch_channel_set_app_flag_key("T38", channel, CF_APP_T38_FAIL); + switch_core_media_reset_t38(session); + switch_core_media_reset_t38(other_session); } else if (status == 200 && switch_channel_test_flag(channel, CF_T38_PASSTHRU) && has_t38 && sip->sip_payload && sip->sip_payload->pl_data) { switch_t38_options_t *t38_options = switch_core_media_extract_t38_options(session, sip->sip_payload->pl_data); @@ -7939,8 +7934,8 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, goto done; } - switch_channel_set_flag(tech_pvt->channel, CF_REINVITE); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Reinvite Codec Error!\n"); + switch_channel_clear_flag(tech_pvt->channel, CF_REINVITE); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Reinvite resulted in codec negotiation failure.\n"); is_ok = 0; } } diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 635a00f5b7..81bfb2b6cf 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -3726,6 +3726,17 @@ static void clear_pmaps(switch_rtp_engine_t *engine) } } +static void restore_pmaps(switch_rtp_engine_t *engine) +{ + payload_map_t *pmap; + int top = 0; + + for (pmap = engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) { + pmap->negotiated = 1; + if (!top++) pmap->current = 1; + } +} + //? SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *session, const char *r_sdp, uint8_t *proceed, switch_sdp_type_t sdp_type) { @@ -3929,22 +3940,30 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s switch_channel_set_flag(session->channel, CF_IMAGE_SDP); if (m->m_port) { - switch_t38_options_t *t38_options = switch_core_media_process_udptl(session, sdp, m); - if (switch_channel_test_app_flag_key("T38", session->channel, CF_APP_T38_NEGOTIATED)) { match = 1; goto done; } - if (switch_true(switch_channel_get_variable(channel, "refuse_t38"))) { + if (switch_channel_var_true(channel, "refuse_t38")) { switch_channel_clear_app_flag_key("T38", session->channel, CF_APP_T38); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 REFUSE on %s\n", + switch_channel_get_name(channel), + sdp_type == SDP_TYPE_RESPONSE ? "response" : "request"); + + restore_pmaps(a_engine); match = 0; - goto done; + + goto t38_done; } else { + switch_t38_options_t *t38_options = switch_core_media_process_udptl(session, sdp, m); const char *var = switch_channel_get_variable(channel, "t38_passthru"); int pass = switch_channel_test_flag(smh->session->channel, CF_T38_PASSTHRU); - - + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 ACCEPT on %s\n", + switch_channel_get_name(channel), + sdp_type == SDP_TYPE_RESPONSE ? "response" : "request"); + if (switch_channel_test_app_flag_key("T38", session->channel, CF_APP_T38)) { if (proceed) *proceed = 0; } @@ -3982,10 +4001,13 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s pass = 0; match = 0; + match = 0; goto done; } - + switch_channel_set_app_flag_key("T38", channel, CF_APP_T38_POSSIBLE); + switch_channel_set_app_flag_key("T38", other_channel, CF_APP_T38_POSSIBLE); + if (switch_true(switch_channel_get_variable(session->channel, "t38_broken_boolean")) && switch_true(switch_channel_get_variable(session->channel, "t38_pass_broken_boolean"))) { switch_channel_set_variable(other_channel, "t38_broken_boolean", "true"); @@ -4036,7 +4058,19 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s /* do nothing here, mod_fax will trigger a response (if it's listening =/) */ - match = 1; + if (switch_channel_test_app_flag_key("T38", channel, CF_APP_T38_POSSIBLE)) { + match = 1; + } else { + + match = 0; + } + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 %s POSSIBLE on %s\n", + switch_channel_get_name(channel), + match ? "IS" : "IS NOT", + sdp_type == SDP_TYPE_RESPONSE ? "response" : "request"); + + goto done; } } else if (m->m_type == sdp_media_audio && m->m_port && got_audio && got_savp) { @@ -5035,6 +5069,8 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s done: + t38_done: + if (parser) { sdp_parser_free(parser); } @@ -5045,6 +5081,30 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s return match; } +//? +SWITCH_DECLARE(void) switch_core_media_reset_t38(switch_core_session_t *session) +{ + switch_rtp_engine_t *a_engine; + switch_media_handle_t *smh; + switch_channel_t *channel = switch_core_session_get_channel(session); + + switch_assert(session); + + if (!(smh = session->media_handle)) { + return; + } + + a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO]; + + restore_pmaps(a_engine); + + switch_channel_set_private(channel, "t38_options", NULL); + switch_channel_clear_flag(channel, CF_T38_PASSTHRU); + switch_channel_clear_app_flag_key("T38", channel, CF_APP_T38); + switch_channel_clear_app_flag_key("T38", channel, CF_APP_T38_REQ); + switch_channel_set_app_flag_key("T38", channel, CF_APP_T38_FAIL); +} + //? SWITCH_DECLARE(int) switch_core_media_toggle_hold(switch_core_session_t *session, int sendonly)