diff --git a/conf/sip_profiles/internal.xml b/conf/sip_profiles/internal.xml index 426264a1c5..b78ea20070 100644 --- a/conf/sip_profiles/internal.xml +++ b/conf/sip_profiles/internal.xml @@ -342,6 +342,13 @@ + + + + diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 31cd058dfa..373601683d 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -230,6 +230,7 @@ typedef enum { PFLAG_PRESENCE_ON_REGISTER, PFLAG_PRESENCE_ON_FIRST_REGISTER, PFLAG_NO_CONNECTION_REUSE, + PFLAG_RENEG_ON_HOLD, /* No new flags below this line */ PFLAG_MAX } PFLAGS; @@ -984,7 +985,7 @@ void sofia_glue_del_every_gateway(sofia_profile_t *profile); void sofia_reg_send_reboot(sofia_profile_t *profile, const char *user, const char *host, const char *contact, const char *user_agent, const char *network_ip); void sofia_glue_restart_all_profiles(void); -void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly); +int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly); const char *sofia_state_string(int state); switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force); void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index fac089d12c..b6d6b74aa6 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2436,6 +2436,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) } else { sofia_clear_pflag(profile, PFLAG_IGNORE_183NOSDP); } + } else if (!strcasecmp(var, "renegotiate-codec-on-hold")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_RENEG_ON_HOLD); + } else { + sofia_clear_pflag(profile, PFLAG_RENEG_ON_HOLD); + } } else if (!strcasecmp(var, "presence-probe-on-register")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER); @@ -3119,6 +3125,12 @@ switch_status_t config_sofia(int reload, char *profile_name) } else { sofia_clear_pflag(profile, PFLAG_IGNORE_183NOSDP); } + } else if (!strcasecmp(var, "renegotiate-codec-on-hold")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_RENEG_ON_HOLD); + } else { + sofia_clear_pflag(profile, PFLAG_RENEG_ON_HOLD); + } } else if (!strcasecmp(var, "presence-probe-on-register")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER); diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 0c23472406..f66993ef6f 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3759,8 +3759,10 @@ switch_status_t sofia_glue_tech_media(private_object_t *tech_pvt, const char *r_ return SWITCH_STATUS_FALSE; } -void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly) +int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly) { + int changed = 0; + if (sendonly && switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED)) { if (!sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) { const char *stream; @@ -3779,6 +3781,7 @@ void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly) switch_channel_set_flag(tech_pvt->channel, CF_LEG_HOLDING); switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE); switch_channel_presence(tech_pvt->channel, "unknown", msg, NULL); + changed = 1; if (tech_pvt->max_missed_hold_packets) { switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_hold_packets); @@ -3805,6 +3808,7 @@ void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly) sofia_set_flag(tech_pvt, TFLAG_SIP_HOLD); switch_channel_set_flag(tech_pvt->channel, CF_LEG_HOLDING); switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE); + changed = 1; } sofia_clear_flag_locked(tech_pvt, TFLAG_HOLD_LOCK); @@ -3838,8 +3842,11 @@ void sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly) switch_channel_clear_flag(tech_pvt->channel, CF_LEG_HOLDING); switch_channel_mark_hold(tech_pvt->channel, SWITCH_FALSE); switch_channel_presence(tech_pvt->channel, "unknown", "unhold", NULL); + changed = 1; } } + + return changed; } void sofia_glue_copy_t38_options(switch_t38_options_t *t38_options, switch_core_session_t *session) @@ -4264,7 +4271,19 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s if (!tech_pvt->hold_laps) { tech_pvt->hold_laps++; - sofia_glue_toggle_hold(tech_pvt, sendonly); + if (sofia_glue_toggle_hold(tech_pvt, sendonly)) { + int reneg = sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_HOLD); + + if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_renegotiate_codec_on_hold"))) { + reneg = switch_true(val); + } + + if (!reneg) { + match = 1; + goto done; + } + } + } }