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
