From 7ffd8f9b54c49e61deada1efc00cfced7616c275 Mon Sep 17 00:00:00 2001 From: Donat Zenichev Date: Thu, 23 Sep 2021 17:02:31 +0300 Subject: [PATCH] TT#138356 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. Change-Id: I4ab1d2d0b7286b05e1fc2cf2a432fdfd220ca72f --- debian/patches/series | 1 + ...ct_emergency_calls_and_let_them_pass.patch | 126 ++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 debian/patches/sipwise/cpslimit_detect_emergency_calls_and_let_them_pass.patch diff --git a/debian/patches/series b/debian/patches/series index fe03d4ed..623df1f7 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -40,3 +40,4 @@ sipwise/port_to_py3k.patch sipwise/db_reg_agent_auth_header.patch sipwise/skip_outbound_auth_if_credentials_empty.patch sipwise/add_support_for_peering_outbound_registration.patch +sipwise/cpslimit_detect_emergency_calls_and_let_them_pass.patch diff --git a/debian/patches/sipwise/cpslimit_detect_emergency_calls_and_let_them_pass.patch b/debian/patches/sipwise/cpslimit_detect_emergency_calls_and_let_them_pass.patch new file mode 100644 index 00000000..908640b8 --- /dev/null +++ b/debian/patches/sipwise/cpslimit_detect_emergency_calls_and_let_them_pass.patch @@ -0,0 +1,126 @@ +--- a/core/AmConfig.cpp ++++ b/core/AmConfig.cpp +@@ -125,6 +125,8 @@ bool AmConfig::AcceptForkedDialo + 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"; + +--- 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(); +--- a/core/AmSessionContainer.cpp ++++ b/core/AmSessionContainer.cpp +@@ -444,13 +444,25 @@ unsigned int AmSessionContainer::getMaxC + 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_c + 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::createSes + 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::createSes + return NULL; + } + +- map app_params; +- parse_app_params(req.hdrs,app_params); +- + AmSession* session = NULL; + if (req.method == "INVITE") { + if (NULL != session_params) { +--- 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 AmThre + 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();