From 74343afda7de7c1b142c6870352224390eb38bb4 Mon Sep 17 00:00:00 2001 From: Donat Zenichev Date: Mon, 13 Jul 2026 13:42:34 +0200 Subject: [PATCH] MT#62266 SessionTimer: introduce `sst_strict_mode` Introduce explicit policy for within-dialog SST support: - whenever remote side (call leg) doesn't explicitly declare it supports timers (with `Supported: timer`), disable all previously set timers for this particular leg - this touches request originator, as well as answerer - requests: only UPDATE and INVITE methods are affected - answers: only positive answers are affected - by default this behavior is always disabled if not enabled explicitly in the profile's config with `sst_strict_mode` - sst_strict_mode takes either `yes` or `no` P.S.: the `sst_strict_mode` must not be initialized to true by default, because RFC 4028 explicitly tells to support the operation even when only one UA understands session timers. So we have to be quite accurate and not enforce the strict mode. Change-Id: Ie6647eb061a73dc052367dbd291589198487093c --- apps/sbc/SBCCallProfile.cpp | 7 ++++++ apps/sbc/etc/auth_b2b.sbcprofile.conf | 1 + apps/sbc/etc/sbc.conf | 6 ++++++ apps/sbc/etc/sst_b2b.sbcprofile.conf | 2 ++ apps/sbc/etc/transparent.sbcprofile.conf | 2 ++ core/plug-in/session_timer/SessionTimer.cpp | 24 +++++++++++++++++---- core/plug-in/session_timer/SessionTimer.h | 3 ++- 7 files changed, 40 insertions(+), 5 deletions(-) diff --git a/apps/sbc/SBCCallProfile.cpp b/apps/sbc/SBCCallProfile.cpp index 3885bcb6..58e9638e 100644 --- a/apps/sbc/SBCCallProfile.cpp +++ b/apps/sbc/SBCCallProfile.cpp @@ -234,6 +234,7 @@ bool SBCCallProfile::readFromConfiguration(const string& name, CP_SST_CFGVAR("", "maximum_timer", sst_b_cfg); CP_SST_CFGVAR("", "session_refresh_method", sst_b_cfg); CP_SST_CFGVAR("", "accept_501_reply", sst_b_cfg); + CP_SST_CFGVAR("", "sst_strict_mode", sst_b_cfg); } if (sst_aleg_enabled.size() && sst_aleg_enabled != "no") { @@ -244,6 +245,7 @@ bool SBCCallProfile::readFromConfiguration(const string& name, CP_SST_CFGVAR("aleg_", "maximum_timer", sst_a_cfg); CP_SST_CFGVAR("aleg_", "session_refresh_method", sst_a_cfg); CP_SST_CFGVAR("aleg_", "accept_501_reply", sst_a_cfg); + CP_SST_CFGVAR("aleg_", "sst_strict_mode", sst_a_cfg); } #undef CP_SST_CFGVAR @@ -553,6 +555,8 @@ bool SBCCallProfile::readFromConfiguration(const string& name, sst_a_cfg.getParameter("session_refresh_method").c_str()); INFO("SBC: accept_501_reply=%s\n", sst_a_cfg.getParameter("accept_501_reply").c_str()); + INFO("SBC: sst_strict_mode=%s\n", + sst_a_cfg.getParameter("sst_strict_mode").c_str()); } INFO("SBC: SST on B leg enabled: '%s'\n", sst_enabled.empty() ? "no" : sst_enabled.c_str()); @@ -567,6 +571,8 @@ bool SBCCallProfile::readFromConfiguration(const string& name, sst_b_cfg.getParameter("session_refresh_method").c_str()); INFO("SBC: accept_501_reply=%s\n", sst_b_cfg.getParameter("accept_501_reply").c_str()); + INFO("SBC: sst_strict_mode=%s\n", + sst_b_cfg.getParameter("sst_strict_mode").c_str()); } INFO("SBC: SIP auth %sabled\n", auth_enabled?"en":"dis"); @@ -776,6 +782,7 @@ void SBCCallProfile::eval_sst_config(ParamReplacerCtx& ctx, "maximum_timer", "session_refresh_method", "accept_501_reply", + "sst_strict_mode", }; for(unsigned int i=0; i diff --git a/core/plug-in/session_timer/SessionTimer.cpp b/core/plug-in/session_timer/SessionTimer.cpp index 6eae4d2c..6ed4431f 100644 --- a/core/plug-in/session_timer/SessionTimer.cpp +++ b/core/plug-in/session_timer/SessionTimer.cpp @@ -269,8 +269,8 @@ void SessionTimer::updateTimer(AmSession* s, const AmSipRequest& req) { remote_timer_aware = key_in_list(getHeader(req.hdrs, SIP_HDR_SUPPORTED, SIP_HDR_SUPPORTED_COMPACT), TIMER_OPTION_TAG); - /* disable timers for this leg if not declare explicitly (UPDATE only) */ - if (req.method == SIP_METH_UPDATE && !remote_timer_aware) { + /* disable timers for this leg if not declare explicitly */ + if (session_timer_conf.StrictMode && !remote_timer_aware) { /* timer is not supported by originator's leg */ DBG("Session timer not supported by request originator's leg, remove session timer intervals"); session_timer_conf.setEnableSessionTimer(false); @@ -369,7 +369,7 @@ void SessionTimer::updateTimer(AmSession* s, const AmSipReply& reply) remote_timer_aware = key_in_list(getHeader(reply.hdrs, SIP_HDR_SUPPORTED, SIP_HDR_SUPPORTED_COMPACT), TIMER_OPTION_TAG); - if (!remote_timer_aware) { + if (session_timer_conf.StrictMode && !remote_timer_aware) { /* timer is not supported by responder's leg */ DBG("Session timer not supported by responder's leg, remove session timer intervals"); session_timer_conf.setEnableSessionTimer(false); @@ -483,7 +483,8 @@ AmSessionTimerConfig::AmSessionTimerConfig() : EnableSessionTimer(DEFAULT_ENABLE_SESSION_TIMER), SessionExpires(SESSION_EXPIRES), MinimumTimer(MINIMUM_TIMER), - MaximumTimer(MAXIMUM_TIMER) + MaximumTimer(MAXIMUM_TIMER), + StrictMode(false) { } @@ -528,6 +529,21 @@ int AmSessionTimerConfig::readFromConfig(AmConfigReader& cfg) MaximumTimer = (unsigned int) maximum_timer; } + /* SST strict mode allows to re-init timers during the session, + * whenever remote side with INVITE/UPDATE method doesn't + * declare `Supported: timer` explicitly. By default always: no. + */ + if(cfg.hasParameter("sst_strict_mode")){ + if (cfg.getParameter("sst_strict_mode", "no") == "yes") { + DBG("SST strict mode is enabled by profile settings (default: no).\n"); + StrictMode = true; + } + else { + DBG("SST strict mode is disabled by profile settings (default: no).\n"); + StrictMode = false; + } + } + return 0; } diff --git a/core/plug-in/session_timer/SessionTimer.h b/core/plug-in/session_timer/SessionTimer.h index 20822040..ace01fa4 100644 --- a/core/plug-in/session_timer/SessionTimer.h +++ b/core/plug-in/session_timer/SessionTimer.h @@ -85,7 +85,8 @@ class AmSessionTimerConfig public: AmSessionTimerConfig(); ~AmSessionTimerConfig(); - + + bool StrictMode; /** Session Timer: Enable Session Timer? returns 0 on invalid value */