From 908b64583291faf45ecbec0bae9fc0b5383ded16 Mon Sep 17 00:00:00 2001 From: Donat Zenichev Date: Thu, 29 Dec 2022 10:14:31 +0100 Subject: [PATCH] MT#55831 Detect emergency calls and let them pass on license limitation (SEMS CE) Remark: this commit is created as an attempt to keep PRO / CE sems repositories consistent in terms of the provided code and functionality. We need to have a possibility to detect emergency calls and let them pass through the SEMS, even if the license limitation (CPSLimit) is triggered. Also taking into account the global policy defined by the cfg parameter 'skip_cpslimit_emergency'. If set to 'yes' (in the code will be treated as True) then we do not drop emergency calls on CPSLimit triggering. If set to 'no' - we treat emergency calls as if they were usual calls in terms of checking CPSLimit license limitation. (real ticket number: TT#138356) Change-Id: I152747271bb5d0a6838f721493fd2660a35e10f8 --- core/AmConfig.cpp | 7 +++++++ core/AmConfig.h | 3 +++ core/AmSessionContainer.cpp | 34 ++++++++++++++++++++++++++++------ core/AmSessionContainer.h | 5 ++++- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/core/AmConfig.cpp b/core/AmConfig.cpp index a1350f9c..1795d20a 100644 --- a/core/AmConfig.cpp +++ b/core/AmConfig.cpp @@ -125,6 +125,8 @@ bool AmConfig::AcceptForkedDialogs = true; bool AmConfig::ShutdownMode = false; unsigned int AmConfig::ShutdownModeErrCode = 503; string AmConfig::ShutdownModeErrReason = "Server shutting down"; + +bool AmConfig::skip_cpslimit_emergency = true; string AmConfig::OptionsTranscoderOutStatsHdr; // empty by default string AmConfig::OptionsTranscoderInStatsHdr; // empty by default @@ -458,6 +460,11 @@ int AmConfig::readConfiguration() } } + // skip_cpslimit_emergency = true - do not drop emergency calls on CPSLimit + // skip_cpslimit_emergency = false - drop emergency calls on CPSLimit + if (cfg.hasParameter("skip_cpslimit_emergency")) + skip_cpslimit_emergency = cfg.getParameter("skip_cpslimit_emergency")=="yes"; + if(cfg.hasParameter("log_sessions")) LogSessions = cfg.getParameter("log_sessions")=="yes"; diff --git a/core/AmConfig.h b/core/AmConfig.h index 50fd5eeb..eb29b62a 100644 --- a/core/AmConfig.h +++ b/core/AmConfig.h @@ -281,6 +281,9 @@ struct AmConfig static AmAudio::ResamplingImplementationType ResamplingImplementationType; + /* Global policy for treating emergency calls on CPSLimit triggering */ + static bool skip_cpslimit_emergency; + /** Read global configuration file and insert values. Maybe overwritten by * command line arguments */ static int readConfiguration(); diff --git a/core/AmSessionContainer.cpp b/core/AmSessionContainer.cpp index 233f55ac..2c56dbc8 100644 --- a/core/AmSessionContainer.cpp +++ b/core/AmSessionContainer.cpp @@ -444,13 +444,25 @@ unsigned int AmSessionContainer::getMaxCPS() return res; } -bool AmSessionContainer::check_and_add_cps() +// we need the emergency_flag to mark emergency calls +// and skip checking CPSLimit for them if the global policy is so +// emergency_flag = True - do not run CPSLimit check for the call +// emergency_flag = False - run CPSLimit check for the call +bool AmSessionContainer::check_and_add_cps(bool emergency_flag) { struct timeval tv, res; gettimeofday(&tv,0); AmLock lock(cps_mut); + // check global policy for dropping emergency calls + if (!AmConfig::skip_cpslimit_emergency && emergency_flag) { + emergency_flag = AmConfig::skip_cpslimit_emergency; + DBG("Emergency call detected, but global policy is to do the CPSLimit check (license).\n"); + } + + if (emergency_flag) DBG("Emergency call detected, skip CPSLimit check (license).\n"); + while (cps_queue.size()) { timersub(&tv, &cps_queue.front(), &res); if (res.tv_sec >= CPS_SAMPLERATE) { @@ -466,7 +478,7 @@ bool AmSessionContainer::check_and_add_cps() max_cps = cps; } - if( CPSLimit && cps > CPSLimit ){ + if( CPSLimit && cps > CPSLimit && !emergency_flag){ DBG("cps_limit %d reached. Not creating session.\n", CPSLimit); return true; } @@ -500,7 +512,20 @@ AmSession* AmSessionContainer::createSession(const AmSipRequest& req, return NULL; } - if (check_and_add_cps()) { + map app_params; + parse_app_params(req.hdrs,app_params); + + // look into P-App-Param list, try to find 'emergency' marker + emergency_flag = false; + map::iterator it; + + it = app_params.find(EMERGENCY_PARAM); + if (it != app_params.end() && (it->first == EMERGENCY_PARAM && it->second == "1")) { + DBG("Emergency parameter detected: <;%s=%s> .\n", it->first.c_str(), it->second.c_str()); + emergency_flag = true; + } + + if (check_and_add_cps(emergency_flag)) { AmSipDialog::reply_error(req,AmConfig::CPSLimitErrCode, AmConfig::CPSLimitErrReason); return NULL; @@ -520,9 +545,6 @@ AmSession* AmSessionContainer::createSession(const AmSipRequest& req, return NULL; } - map app_params; - parse_app_params(req.hdrs,app_params); - AmSession* session = NULL; if (req.method == "INVITE") { if (NULL != session_params) { diff --git a/core/AmSessionContainer.h b/core/AmSessionContainer.h index e1d58beb..514c14cf 100644 --- a/core/AmSessionContainer.h +++ b/core/AmSessionContainer.h @@ -37,6 +37,8 @@ #include #include +#define EMERGENCY_PARAM "emergency" + using std::string; /** @@ -96,7 +98,8 @@ class AmSessionContainer : public AmThread unsigned int CPSLimit; unsigned int CPSHardLimit; - bool check_and_add_cps(); + bool check_and_add_cps(bool emergency_flag); + bool emergency_flag; public: static AmSessionContainer* instance();