Module: sems
Branch: master
Commit: 3af5aa50312473fa61da2cd476b69d1136d70dd1
URL:    
http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=3af5aa50312473fa61da2cd476b69d1136d70dd1

Author: Stefan Sayer <[email protected]>
Committer: Stefan Sayer <[email protected]>
Date:   Thu Mar  8 15:19:41 2012 +0100

sbc: tear down calls through RPC (DI, e.g. XMLRPC)

---

 apps/sbc/SBC.cpp                      |   56 +++++++++++++++++++++++++++++++++
 apps/sbc/SBC.h                        |    7 ++++
 apps/sbc/tools/sems-sbc-teardown-call |   19 +++++++++++
 core/ampi/SBCCallControlAPI.h         |   13 +++++++
 doc/Readme.sbc.txt                    |    4 ++
 5 files changed, 99 insertions(+), 0 deletions(-)

diff --git a/apps/sbc/SBC.cpp b/apps/sbc/SBC.cpp
index d344ef6..fdc9c8f 100644
--- a/apps/sbc/SBC.cpp
+++ b/apps/sbc/SBC.cpp
@@ -363,6 +363,9 @@ void SBCFactory::invoke(const string& method, const AmArg& 
args,
   } else if (method == "loadCallcontrolModules"){
     args.assertArrayFmt("s");
     loadCallcontrolModules(args,ret);
+  } else if (method == "postControlCmd"){
+    args.assertArrayFmt("ss"); // at least call-ltag, cmd
+    postControlCmd(args,ret);
   } else if(method == "_list"){ 
     ret.push(AmArg("listProfiles"));
     ret.push(AmArg("reloadProfiles"));
@@ -373,6 +376,7 @@ void SBCFactory::invoke(const string& method, const AmArg& 
args,
     ret.push(AmArg("getRegexMapNames"));
     ret.push(AmArg("setRegexMap"));
     ret.push(AmArg("loadCallcontrolModules"));
+    ret.push(AmArg("postControlCmd"));
   }  else
     throw AmDynInvoke::NotImplemented(method);
 }
@@ -574,6 +578,22 @@ void SBCFactory::loadCallcontrolModules(const AmArg& args, 
AmArg& ret) {
   ret.push("OK");
 }
 
+void SBCFactory::postControlCmd(const AmArg& args, AmArg& ret) {
+  SBCControlEvent* evt;
+  if (args.size()<3) {
+    evt = new SBCControlEvent(args[1].asCStr());
+  } else {
+    evt = new SBCControlEvent(args[1].asCStr(), args[2]);
+  }
+  if (!AmSessionContainer::instance()->postEvent(args[0].asCStr(), evt)) {
+    ret.push(404);
+    ret.push("Not found");
+  } else {
+    ret.push(202);
+    ret.push("Accepted");
+  }
+}
+
 SBCDialog::SBCDialog(const SBCCallProfile& call_profile)
   : m_state(BB_Init),
     auth(NULL),
@@ -864,9 +884,25 @@ void SBCDialog::process(AmEvent* ev)
     }
   }
 
+  SBCControlEvent* ctl_event;
+  if (ev->event_id == SBCControlEvent_ID &&
+      (ctl_event = dynamic_cast<SBCControlEvent*>(ev)) != NULL) {
+    onControlCmd(ctl_event->cmd, ctl_event->params);
+    return;
+  }
+
   AmB2BCallerSession::process(ev);
 }
 
+void SBCDialog::onControlCmd(string& cmd, AmArg& params) {
+  if (cmd == "teardown") {
+    DBG("teardown requested from control cmd\n");
+    stopCall();
+    return;
+  }
+  DBG("ignoring unknown control cmd : '%s'\n", cmd.c_str());
+}
+
 int SBCDialog::relayEvent(AmEvent* ev) {
   if (isActiveFilter(call_profile.headerfilter) && (ev->event_id == 
B2BSipRequest)) {
     // header filter
@@ -1525,6 +1561,17 @@ int SBCCalleeSession::relayEvent(AmEvent* ev) {
   return AmB2BCalleeSession::relayEvent(ev);
 }
 
+void SBCCalleeSession::process(AmEvent* ev) {
+  SBCControlEvent* ctl_event;
+  if (ev->event_id == SBCControlEvent_ID &&
+      (ctl_event = dynamic_cast<SBCControlEvent*>(ev)) != NULL) {
+    onControlCmd(ctl_event->cmd, ctl_event->params);
+    return;
+  }
+
+  AmB2BCalleeSession::process(ev);
+}
+
 void SBCCalleeSession::onSipRequest(const AmSipRequest& req) {
   // AmB2BSession does not call AmSession::onSipRequest for 
   // forwarded requests - so lets call event handlers here
@@ -1590,6 +1637,15 @@ void SBCCalleeSession::onSendRequest(AmSipRequest& req, 
int flags)
   AmB2BCalleeSession::onSendRequest(req, flags);
 }
 
+void SBCCalleeSession::onControlCmd(string& cmd, AmArg& params) {
+  if (cmd == "teardown") {
+    DBG("relaying teardown control cmd to A leg\n");
+    relayEvent(new SBCControlEvent(cmd, params));
+    return;
+  }
+  DBG("ignoring unknown control cmd : '%s'\n", cmd.c_str());
+}
+
 int SBCCalleeSession::filterBody(AmSdp& sdp, bool is_a2b) {
   if (call_profile.sdpfilter_enabled) {
     // normalize SDP
diff --git a/apps/sbc/SBC.h b/apps/sbc/SBC.h
index 1150db8..750069a 100644
--- a/apps/sbc/SBC.h
+++ b/apps/sbc/SBC.h
@@ -60,6 +60,7 @@ class SBCFactory: public AmSessionFactory,
   void getRegexMapNames(const AmArg& args, AmArg& ret);
   void setRegexMap(const AmArg& args, AmArg& ret);
   void loadCallcontrolModules(const AmArg& args, AmArg& ret);
+  void postControlCmd(const AmArg& args, AmArg& ret);
 
   string getActiveProfileMatch(string& profile_rule, const AmSipRequest& req,
                               const string& app_param, AmUriParser& 
ruri_parser,
@@ -193,6 +194,8 @@ class SBCDialog : public AmB2BCallerSession, public 
CredentialHolder
   bool onOtherReply(const AmSipReply& reply);
   void onOtherBye(const AmSipRequest& req);
 
+  void onControlCmd(string& cmd, AmArg& params);
+
   int filterBody(AmSdp& sdp, bool is_a2b);
 
   void createCalleeSession();
@@ -213,6 +216,8 @@ class SBCCalleeSession
 
   /* bool onOtherReply(const AmSipReply& reply); */
 
+  void onControlCmd(string& cmd, AmArg& params);
+
   int filterBody(AmSdp& sdp, bool is_a2b);
 
  public:
@@ -220,6 +225,8 @@ class SBCCalleeSession
                   const SBCCallProfile& call_profile); 
   ~SBCCalleeSession();
 
+  void process(AmEvent* ev);
+
   inline UACAuthCred* getCredentials();
   
   void setAuthHandler(AmSessionEventHandler* h) { auth = h; }
diff --git a/apps/sbc/tools/sems-sbc-teardown-call 
b/apps/sbc/tools/sems-sbc-teardown-call
new file mode 100755
index 0000000..d89e0d2
--- /dev/null
+++ b/apps/sbc/tools/sems-sbc-teardown-call
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import sys
+from xmlrpclib import *
+
+if len(sys.argv) != 2:
+       print "usage: %s <ltag/ID of call to tear down>" % sys.argv[0]
+       sys.exit(1)
+
+s = ServerProxy('http://localhost:8090')
+print "Active calls: %d" % s.calls()
+res = s.di('sbc', 'postControlCmd', sys.argv[1], "teardown")
+
+if res[0] >= 200 and res[0] < 300:
+  print "OK"
+  sys.exit(0)
+else:
+  print "Error: %s" % str(res)
+  sys.exit(2)
diff --git a/core/ampi/SBCCallControlAPI.h b/core/ampi/SBCCallControlAPI.h
index 163823c..9f2a83a 100644
--- a/core/ampi/SBCCallControlAPI.h
+++ b/core/ampi/SBCCallControlAPI.h
@@ -54,4 +54,17 @@ struct SBCCallTimerEvent : public AmEvent {
     timer_id(timer_id), timer_action(timer_action), timeout(timeout) { }
 };
 
+#define SBCControlEvent_ID -564
+struct SBCControlEvent : public AmEvent {
+  string cmd;
+  AmArg params;
+
+  SBCControlEvent(const string& cmd, const AmArg& params)
+    : AmEvent(SBCControlEvent_ID), cmd(cmd), params(params) { }
+
+  SBCControlEvent(const string& cmd)
+    : AmEvent(SBCControlEvent_ID), cmd(cmd) { }
+
+};
+
 #endif
diff --git a/doc/Readme.sbc.txt b/doc/Readme.sbc.txt
index 1d6646d..fb3e769 100644
--- a/doc/Readme.sbc.txt
+++ b/doc/Readme.sbc.txt
@@ -25,6 +25,7 @@ Features
  o call timer
  o prepaid accounting
  o CDR generation
+ o call teardown from external control through RPC
 
 SBC Profiles
 ------------
@@ -85,6 +86,9 @@ is provided and installed to trigger the reload (through 
XMLRPC):
   sems-sbc-get-activeprofile                    get active_profile
   sems-sbc-set-activeprofile <active_profile>   set active_profile
 
+  sems-sbc-teardown-call <call_ltag>            tear down call (use e.g. 
monitoring's
+                                                sems-list-active-calls to get 
the ltag)
+
 The xmlrpc2di module must be loaded and the XMLRPC control server bound to 
port 8090 for
 the scripts to work.
 

_______________________________________________
Semsdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/semsdev

Reply via email to