From 516db24b7539049903f2ace63821ecafb863015e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Oct 2009 23:01:37 +0000 Subject: [PATCH] SFSIP-180 report hack in sofia lib to pekka for better answer git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@15190 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- .../libsofia-sip-ua/nua/nua_session.c | 9 +++- src/mod/endpoints/mod_sofia/sofia.c | 35 +++++++++++----- src/mod/endpoints/mod_sofia/sofia_glue.c | 42 +++++++++++++------ 3 files changed, 60 insertions(+), 26 deletions(-) diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c index 4459a9ede5..2630dc2913 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c @@ -943,14 +943,19 @@ static int nua_session_client_response(nua_client_request_t *cr, SU_DEBUG_5(("nua(%p): %s: %s %s in %u %s\n", \ (void *)nh, cr->cr_method_name, (m), received, status, phrase)) + retry: + if (!ss || !sip || 300 <= status) /* Xyzzy */; else if (!session_get_description(sip, &sdp, &len)) /* No SDP */; else if (cr->cr_answer_recv) { /* Ignore spurious answers after completing O/A */ - LOG3("ignoring duplicate"); - sdp = NULL; + //LOG3("ignoring duplicate"); + //sdp = NULL; + // we need to make sure its *actually* a dup, so we can't assume for now. + cr->cr_answer_recv = 0; + goto retry; } else if (cr->cr_offer_sent) { /* case 1: answer to our offer */ diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index c4a5d82d6b..eb7975e080 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -3474,6 +3474,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, switch_core_session_t *other_session = NULL; switch_channel_t *other_channel = NULL; char st[80] = ""; + int is_dup_sdp = 0; tl_gets(tags, NUTAG_CALLSTATE_REF(ss_state), @@ -3519,18 +3520,23 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, if (r_sdp) { sdp_parser_t *parser; sdp_session_t *sdp; + + if (!switch_strlen_zero(tech_pvt->remote_sdp_str) && !strcmp(tech_pvt->remote_sdp_str, r_sdp)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Duplicate SDP\n%s\n", r_sdp); + is_dup_sdp = 1; + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote SDP:\n%s\n", r_sdp); + tech_pvt->remote_sdp_str = switch_core_session_strdup(session, r_sdp); + switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote SDP:\n%s\n", r_sdp); - tech_pvt->remote_sdp_str = switch_core_session_strdup(session, r_sdp); - switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp); - - if ( sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && (parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) { - if ((sdp = sdp_session(parser))) { - sofia_glue_set_r_sdp_codec_string(channel, (tech_pvt->profile?tech_pvt->profile->codec_string:NULL), sdp); + if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && (parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) { + if ((sdp = sdp_session(parser))) { + sofia_glue_set_r_sdp_codec_string(channel, (tech_pvt->profile?tech_pvt->profile->codec_string:NULL), sdp); + } + sdp_parser_free(parser); } - sdp_parser_free(parser); + sofia_glue_pass_sdp(tech_pvt, (char *) r_sdp); } - sofia_glue_pass_sdp(tech_pvt, (char *) r_sdp); } } @@ -3848,6 +3854,8 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, } goto done; } else { + sofia_set_flag_locked(tech_pvt, TFLAG_REINVITE); + if (tech_pvt->num_codecs) { if ((parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) { if ((sdp = sdp_session(parser))) { @@ -3861,14 +3869,15 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, goto done; } sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 0); - sofia_set_flag_locked(tech_pvt, TFLAG_REINVITE); + if (sofia_glue_activate_rtp(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Reinvite RTP Error!\n"); is_ok = 0; switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Processing Reinvite\n"); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Processing updated SDP\n"); } else { + sofia_clear_flag_locked(tech_pvt, TFLAG_REINVITE); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Reinvite Codec Error!\n"); is_ok = 0; } @@ -3891,6 +3900,10 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, } break; case nua_callstate_ready: + if (r_sdp && !is_dup_sdp && switch_rtp_ready(tech_pvt->rtp_session)) { + ss_state = nua_callstate_completed; + goto state_process; + } if (r_sdp && sofia_test_flag(tech_pvt, TFLAG_NOSDP_REINVITE)) { sdp_parser_t *parser; diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index abcc5a6e7d..d6100e28ab 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -2321,7 +2321,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f //const char *port = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE); char *remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session); switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session); - + if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_audio_ip) && remote_port == tech_pvt->remote_sdp_audio_port) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n", switch_channel_get_name(tech_pvt->channel)); goto video; @@ -2970,7 +2970,6 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t * } else if (m->m_type == sdp_media_audio && m->m_port && !got_audio) { sdp_rtpmap_t *map; - for (attr = m->m_attributes; attr; attr = attr->a_next) { if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) { ptime = atoi(attr->a_value); @@ -3065,26 +3064,43 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t * greed: x = 0; - if (tech_pvt->rm_encoding) { + if (tech_pvt->rm_encoding) {// && !sofia_test_flag(tech_pvt, TFLAG_REINVITE)) { + char *remote_host = tech_pvt->remote_sdp_audio_ip; + switch_port_t remote_port = tech_pvt->remote_sdp_audio_port; + int same = 0; + + if (switch_rtp_ready(tech_pvt->rtp_session)) { + remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session); + remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session); + } + for (map = m->m_rtpmaps; map; map = map->rm_next) { - if (map->rm_pt < 96) { + if (switch_strlen_zero(map->rm_encoding) && map->rm_pt < 96) { match = (map->rm_pt == tech_pvt->pt) ? 1 : 0; } else { match = strcasecmp(switch_str_nil(map->rm_encoding), tech_pvt->iananame) ? 0 : 1; } - if (match && connection->c_address && tech_pvt->remote_sdp_audio_ip && - !strcmp(connection->c_address, tech_pvt->remote_sdp_audio_ip) && m->m_port == tech_pvt->remote_sdp_audio_port) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Our existing sdp is still good [%s %s:%d], let's keep it.\n", - tech_pvt->rm_encoding, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port); - got_audio = 1; + if (match && connection->c_address && remote_host && + !strcmp(connection->c_address, remote_host) && m->m_port == remote_port) { + same = 1; + } else { + same = 0; break; } } + + if (same) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "Our existing sdp is still good [%s %s:%d], let's keep it.\n", + tech_pvt->rm_encoding, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port); + got_audio = 1; + } else { + match = 0; + got_audio = 0; + } } - - - + for (map = m->m_rtpmaps; map; map = map->rm_next) { int32_t i; uint32_t near_rate = 0; @@ -3144,7 +3160,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t * switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio Codec Compare [%s:%d:%u:%d]/[%s:%d:%u:%d]\n", rm_encoding, map->rm_pt, (int) map->rm_rate, ptime, imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000); - if (map->rm_pt < 96) { + if (switch_strlen_zero(map->rm_encoding) && map->rm_pt < 96) { match = (map->rm_pt == imp->ianacode) ? 1 : 0; } else { match = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1;