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

Reply via email to