Module: sems Branch: master Commit: cae21d6b3c432b64cad423dc277e98aa1ed92b32 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=cae21d6b3c432b64cad423dc277e98aa1ed92b32
Author: Václav Kubart <[email protected]> Committer: Václav Kubart <[email protected]> Date: Wed Nov 13 10:29:14 2013 +0100 sbc: strict control over hold offer --- apps/sbc/SBCCallLeg.cpp | 59 ++++++++++++++++++++++++++++-------------- apps/sbc/SBCCallLeg.h | 1 + apps/sbc/SBCCallProfile.cpp | 25 +++++++++++++++--- apps/sbc/SBCCallProfile.h | 13 ++++++--- doc/Readme.sbc.txt | 30 ++++++++++++++++++++++ 5 files changed, 100 insertions(+), 28 deletions(-) diff --git a/apps/sbc/SBCCallLeg.cpp b/apps/sbc/SBCCallLeg.cpp index 9019aea..8441396 100644 --- a/apps/sbc/SBCCallLeg.cpp +++ b/apps/sbc/SBCCallLeg.cpp @@ -1583,39 +1583,60 @@ void SBCCallLeg::resumeRejected() CallLeg::resumeRejected(); } -static void zero_connection(SdpConnection &c) +static void replace_address(SdpConnection &c, const string &ip) { if (!c.address.empty()) { - if (c.network == NT_IN) { - if (c.addrType == AT_V4) { - c.address = "0.0.0.0"; - return; - } - // TODO: IPv6? + if (c.addrType == AT_V4) { + c.address = ip; + return; } + // TODO: IPv6? + DBG("unsupported address type for replacing IP"); } - - DBG("unsupported connection type for marking with 0.0.0.0"); } -static void alterHoldRequest(AmSdp &sdp, bool mark_zero_con, bool enable_recv) +static void alterHoldRequest(AmSdp &sdp, SBCCallProfile::HoldSettings::Activity a, const string &ip) { - if (mark_zero_con) zero_connection(sdp.conn); + if (!ip.empty()) replace_address(sdp.conn, ip); for (vector<SdpMedia>::iterator m = sdp.media.begin(); m != sdp.media.end(); ++m) { - if (mark_zero_con) zero_connection(m->conn); - m->recv = enable_recv; + if (!ip.empty()) replace_address(m->conn, ip); + m->recv = (a == SBCCallProfile::HoldSettings::sendrecv || a == SBCCallProfile::HoldSettings::recvonly); + m->send = (a == SBCCallProfile::HoldSettings::sendrecv || a == SBCCallProfile::HoldSettings::sendonly); + } +} + +void SBCCallLeg::alterHoldRequestImpl(AmSdp &sdp) +{ + if (call_profile.hold_settings.mark_zero_connection(a_leg)) { + static const string zero("0.0.0.0"); + ::alterHoldRequest(sdp, call_profile.hold_settings.activity(a_leg), zero); + } + else { + if (getRtpRelayMode() == RTP_Direct) { + // we can not put our IP there if not relaying, using empty not to + // overwrite existing addresses + static const string empty; + ::alterHoldRequest(sdp, call_profile.hold_settings.activity(a_leg), empty); + } + else { + // use public IP to be put into connection addresses (overwrite 0.0.0.0 + // there) + ::alterHoldRequest(sdp, call_profile.hold_settings.activity(a_leg), advertisedIP()); + } } } void SBCCallLeg::alterHoldRequest(AmSdp &sdp) { - TRACE("altering B2B hold request\n"); + TRACE("altering B2B hold request(%s, %s, %s)\n", + call_profile.hold_settings.alter_b2b(a_leg) ? "alter B2B" : "do not alter B2B", + call_profile.hold_settings.mark_zero_connection(a_leg) ? "0.0.0.0" : "own IP", + call_profile.hold_settings.activity_str(a_leg).c_str() + ); if (!call_profile.hold_settings.alter_b2b(a_leg)) return; - ::alterHoldRequest(sdp, - call_profile.hold_settings.mark_zero_connection(a_leg), - call_profile.hold_settings.recv(a_leg)); + alterHoldRequestImpl(sdp); } void SBCCallLeg::createHoldRequest(AmSdp &sdp) @@ -1645,9 +1666,7 @@ void SBCCallLeg::createHoldRequest(AmSdp &sdp) m.payloads.push_back(SdpPayload(0)); } - ::alterHoldRequest(sdp, - call_profile.hold_settings.mark_zero_connection(a_leg), - call_profile.hold_settings.recv(a_leg)); + alterHoldRequestImpl(sdp); AmB2BMedia *ms = getMediaSession(); if (ms) ms->replaceOffer(sdp, a_leg); diff --git a/apps/sbc/SBCCallLeg.h b/apps/sbc/SBCCallLeg.h index 9f12b2f..ed7775f 100644 --- a/apps/sbc/SBCCallLeg.h +++ b/apps/sbc/SBCCallLeg.h @@ -105,6 +105,7 @@ class SBCCallLeg : public CallLeg, public CredentialHolder void logCallStart(const AmSipReply& reply); void logCanceledCall(); + void alterHoldRequestImpl(AmSdp &sdp); // do the SDP update (called by alterHoldRequest) public: diff --git a/apps/sbc/SBCCallProfile.cpp b/apps/sbc/SBCCallProfile.cpp index 69913d0..e35de3a 100644 --- a/apps/sbc/SBCCallProfile.cpp +++ b/apps/sbc/SBCCallProfile.cpp @@ -1644,23 +1644,40 @@ void SBCCallProfile::HoldSettings::readConfig(AmConfigReader &cfg) { // store string values for later evaluation aleg.mark_zero_connection_str = cfg.getParameter("hold_zero_connection_aleg"); - aleg.recv_str = cfg.getParameter("hold_enable_recv_aleg"); + aleg.activity_str = cfg.getParameter("hold_activity_aleg"); aleg.alter_b2b_str = cfg.getParameter("hold_alter_b2b_aleg"); bleg.mark_zero_connection_str = cfg.getParameter("hold_zero_connection_bleg"); - bleg.recv_str = cfg.getParameter("hold_enable_recv_bleg"); + bleg.activity_str = cfg.getParameter("hold_activity_bleg"); bleg.alter_b2b_str = cfg.getParameter("hold_alter_b2b_bleg"); } +bool SBCCallProfile::HoldSettings::HoldParams::setActivity(const string &s) +{ + if (s == "sendrecv") activity = sendrecv; + else if (s == "sendonly") activity = sendonly; + else if (s == "recvonly") activity = recvonly; + else if (s == "inactive") activity = inactive; + else { + ERROR("unsupported hold stream activity: %s\n", s.c_str()); + return false; + } + + return true; +} + bool SBCCallProfile::HoldSettings::evaluate(ParamReplacerCtx& ctx, const AmSipRequest& req) { REPLACE_BOOL(aleg.mark_zero_connection_str, aleg.mark_zero_connection); - REPLACE_BOOL(aleg.recv_str, aleg.recv); + REPLACE_STR(aleg.activity_str); REPLACE_BOOL(aleg.alter_b2b_str, aleg.alter_b2b); REPLACE_BOOL(bleg.mark_zero_connection_str, bleg.mark_zero_connection); - REPLACE_BOOL(bleg.recv_str, bleg.recv); + REPLACE_STR(bleg.activity_str); REPLACE_BOOL(bleg.alter_b2b_str, bleg.alter_b2b); + if (!aleg.activity_str.empty() && !aleg.setActivity(aleg.activity_str)) return false; + if (!bleg.activity_str.empty() && !bleg.setActivity(bleg.activity_str)) return false; + return true; } diff --git a/apps/sbc/SBCCallProfile.h b/apps/sbc/SBCCallProfile.h index da47c15..b224649 100644 --- a/apps/sbc/SBCCallProfile.h +++ b/apps/sbc/SBCCallProfile.h @@ -282,21 +282,26 @@ struct SBCCallProfile // hold settings class HoldSettings { + public: + enum Activity { sendrecv, sendonly, recvonly, inactive }; + private: struct HoldParams { // non-replaced params - string mark_zero_connection_str, recv_str, alter_b2b_str; + string mark_zero_connection_str, activity_str, alter_b2b_str; bool mark_zero_connection; - bool recv; // sendrecv/recvonly (if set) X sendonly/inactive (if unset) + Activity activity; bool alter_b2b; // transform B2B hold requests (not locally generated ones) - HoldParams(): mark_zero_connection(false), recv(false), alter_b2b(false) { } + bool setActivity(const string &s); + HoldParams(): mark_zero_connection(false), activity(sendonly), alter_b2b(false) { } } aleg, bleg; public: bool mark_zero_connection(bool a_leg) { return a_leg ? aleg.mark_zero_connection : bleg.mark_zero_connection; } - bool recv(bool a_leg) { return a_leg ? aleg.recv : bleg.recv; } + Activity activity(bool a_leg) { return a_leg ? aleg.activity : bleg.activity; } + const string &activity_str(bool a_leg) { return a_leg ? aleg.activity_str : bleg.activity_str; } bool alter_b2b(bool a_leg) { return a_leg ? aleg.alter_b2b : bleg.alter_b2b; } void readConfig(AmConfigReader &cfg); diff --git a/doc/Readme.sbc.txt b/doc/Readme.sbc.txt index ea0d06f..383a7ce 100644 --- a/doc/Readme.sbc.txt +++ b/doc/Readme.sbc.txt @@ -595,6 +595,36 @@ enable_aleg_session_timer not set, SST is enabled for both legs. Likewise, if aleg_session_expires etc. is not set, the SST configuration of the B leg is used (session_expires, minimum_timer etc). + +Call hold configuration +----------------------- + +SBC detects hold offer in SDP and according to configured parameters it can +alter the hold requests passing through. (this may be handy for example if there +is need to change "sendonly" to "sendrecv" for correct passing hold music +through NATs) + +hold_alter_b2b_aleg / hold_alter_b2b_bleg + + If set to "yes" SBC alters B2B hold requests according to hold settings. + + If set to "no" hold settings is used for locally generated hold requests only. + +hold_zero_connection_aleg / hold_zero_connection_bleg + + If set to "yes" all connections within SDP are replaced with 0.0.0.0. + + If set to "no" SBC tries to put its own media IP everywhere (to replace + 0.0.0.0). Note that if SBC is not doing rtp relay, it can not replace IP + with its own address and the original one is kept there. + +hold_activity_aleg / hold_activity_bleg + + Force "stream activity" (send/recv) on hold offer. + + Possible values: sendrecv, sendonly, recvonly, inactive + + Call control modules -------------------- Call control (CC) modules for the sbc application implement business _______________________________________________ Semsdev mailing list [email protected] http://lists.iptel.org/mailman/listinfo/semsdev
