diff --git a/conf/sip_profiles/internal.xml b/conf/sip_profiles/internal.xml index ee3f6fb8bc..c6d23c170b 100644 --- a/conf/sip_profiles/internal.xml +++ b/conf/sip_profiles/internal.xml @@ -146,7 +146,10 @@ + + + diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 1153562c5a..2023910e20 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -409,6 +409,29 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session) } } } else { + /* This if statement check and handles the 3pcc proxy mode */ + if ((tech_pvt->profile->pflags & PFLAG_3PCC_PROXY) && switch_test_flag(tech_pvt, TFLAG_3PCC)) { + /* Send the 200 OK */ + nua_respond(tech_pvt->nh, SIP_200_OK, + SIPTAG_CONTACT_STR(tech_pvt->profile->url), + SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str), + SOATAG_REUSE_REJECTED(1), + SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END()); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "3PCC-PROXY, Sent a 200 OK, waiting for ACK\n"); + + /* Unlock the session signal to allow the ack to make it in */ + // Maybe we should timeout? + switch_core_session_signal_unlock(session); + while(switch_channel_ready(channel) && !switch_test_flag(tech_pvt, TFLAG_3PCC_HAS_ACK)) { + switch_yield(1000); + } + // if we never got the ack should we PUNT? + /* Get the lock back before we continue */ + switch_core_session_signal_lock(session); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "3PCC-PROXY, Done waiting for ACK\n"); + } + if ((is_proxy && !b_sdp) || switch_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) || !tech_pvt->iananame) { switch_clear_flag_locked(tech_pvt, TFLAG_LATE_NEGOTIATION); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 726b3ecf0b..edd38544fe 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -162,7 +162,8 @@ typedef enum { PFLAG_DISABLE_SRTP_AUTH = (1 << 25), PFLAG_FUNNY_STUN = (1 << 26), PFLAG_STUN_ENABLED = (1 << 27), - PFLAG_STUN_AUTO_DISABLE = (1 << 28) + PFLAG_STUN_AUTO_DISABLE = (1 << 28), + PFLAG_3PCC_PROXY = (1 << 29) } PFLAGS; typedef enum { @@ -207,7 +208,8 @@ typedef enum { TFLAG_TPORT_LOG = (1 << 27), TFLAG_SENT_UPDATE = (1 << 28), TFLAG_PROXY_MEDIA = (1 << 29), - TFLAG_HOLD_LOCK = (1 << 30) + TFLAG_HOLD_LOCK = (1 << 30), + TFLAG_3PCC_HAS_ACK = (1 << 31) } TFLAGS; struct mod_sofia_globals { diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index c2652d2476..41e4e89e71 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1643,6 +1643,9 @@ switch_status_t config_sofia(int reload, char *profile_name) if (switch_true(val)) { profile->pflags |= PFLAG_3PCC; } + else if(!strcasecmp(val, "proxy")){ + profile->pflags |= PFLAG_3PCC_PROXY; + } } else if (!strcasecmp(var, "accept-blind-auth")) { if (switch_true(val)) { profile->pflags |= PFLAG_BLIND_AUTH; @@ -2432,6 +2435,15 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str), SOATAG_REUSE_REJECTED(1), SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), TAG_END()); + } else if(profile->pflags & PFLAG_3PCC_PROXY){ + //3PCC proxy mode delays the 200 OK until the call is answered + switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOSDP"); + switch_set_flag_locked(tech_pvt, TFLAG_3PCC); + sofia_glue_tech_choose_port(tech_pvt, 0); + sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 0); + switch_channel_set_flag(channel, TFLAG_LATE_NEGOTIATION); + //Moves into CS_INIT so call moves forward into the dialplan + switch_channel_set_state(channel, CS_INIT); } else { switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "3PCC DISABLED"); switch_channel_hangup(channel, SWITCH_CAUSE_MANDATORY_IE_MISSING); @@ -2658,10 +2670,17 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTP Error!\n"); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); } - if (switch_channel_get_state(channel) == CS_HIBERNATE && switch_test_flag(tech_pvt, TFLAG_3PCC)) { - switch_set_flag_locked(tech_pvt, TFLAG_READY); - switch_channel_set_state(channel, CS_INIT); - switch_set_flag(tech_pvt, TFLAG_SDP); + + if (switch_test_flag(tech_pvt, TFLAG_3PCC)) { + /* Check if we are in 3PCC proxy mode, if so then set the flag to indicate we received the ack */ + if (profile->pflags & PFLAG_3PCC_PROXY ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "3PCC-PROXY, Got my ACK\n"); + switch_set_flag(tech_pvt, TFLAG_3PCC_HAS_ACK); + } else if (switch_channel_get_state(channel) == CS_HIBERNATE) { + switch_set_flag_locked(tech_pvt, TFLAG_READY); + switch_channel_set_state(channel, CS_INIT); + switch_set_flag(tech_pvt, TFLAG_SDP); + } } goto done; }