From dfbf9816c9d72bacd54abaa598d25ffa06b3ab80 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Tue, 11 Nov 2008 14:43:52 +0000 Subject: [PATCH] o onInvite event o early dialogs git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@1127 8eb893ce-cfd4-0310-b710-fb5ebe64c474 --- apps/dsm/DSM.cpp | 3 +++ apps/dsm/DSM.h | 1 + apps/dsm/DSMCoreModule.cpp | 17 +++++++++++++- apps/dsm/DSMCoreModule.h | 1 + apps/dsm/DSMDialog.cpp | 38 +++++++++++++++++++++++++++++--- apps/dsm/DSMDialog.h | 2 ++ apps/dsm/DSMModule.h | 2 +- apps/dsm/DSMSession.cpp | 3 ++- apps/dsm/DSMSession.h | 13 ++++++++++- apps/dsm/DSMStateEngine.cpp | 17 ++++++++------ apps/dsm/DSMStateEngine.h | 8 +++++-- apps/dsm/doc/dsm_syntax.txt | 13 +++++++++++ apps/dsm/etc/dsm.conf | 5 +++++ apps/dsm/mods/mod_uri/ModUri.cpp | 3 ++- apps/dsm/mods/mod_uri/ModUri.h | 2 +- 15 files changed, 110 insertions(+), 18 deletions(-) diff --git a/apps/dsm/DSM.cpp b/apps/dsm/DSM.cpp index 9d9e5749..2ec2847b 100644 --- a/apps/dsm/DSM.cpp +++ b/apps/dsm/DSM.cpp @@ -56,6 +56,7 @@ DSMFactory* DSMFactory::instance() string DSMFactory::InboundStartDiag; string DSMFactory::OutboundStartDiag; map DSMFactory::config; +bool DSMFactory::RunInviteEvent; DSMFactory::DSMFactory(const string& _app_name) : AmSessionFactory(_app_name), @@ -185,6 +186,8 @@ int DSMFactory::onLoad() cfg.begin(); it != cfg.end(); it++) config[it->first] = it->second; + RunInviteEvent = cfg.getParameter("run_invite_event")=="yes"; + return 0; } diff --git a/apps/dsm/DSM.h b/apps/dsm/DSM.h index 9e2d7077..f4145b2c 100644 --- a/apps/dsm/DSM.h +++ b/apps/dsm/DSM.h @@ -67,6 +67,7 @@ public: static DSMFactory* instance(); static map config; + static bool RunInviteEvent; int onLoad(); AmSession* onInvite(const AmSipRequest& req); diff --git a/apps/dsm/DSMCoreModule.cpp b/apps/dsm/DSMCoreModule.cpp index 2da52f32..4b631f52 100644 --- a/apps/dsm/DSMCoreModule.cpp +++ b/apps/dsm/DSMCoreModule.cpp @@ -80,7 +80,7 @@ DSMAction* DSMCoreModule::getAction(const string& from_str) { DEF_CMD("stopRecord", SCStopRecordAction); DEF_CMD("closePlaylist", SCClosePlaylistAction); DEF_CMD("addSeparator", SCAddSeparatorAction); - + DEF_CMD("connectMedia", SCConnectMediaAction); DEF_CMD("set", SCSetAction); DEF_CMD("append", SCAppendAction); @@ -142,6 +142,12 @@ DSMCondition* DSMCoreModule::getCondition(const string& from_str) { if (cmd == "eventTest") return new TestDSMCondition(params, DSMCondition::DSMEvent); + if (cmd == "invite") + return new TestDSMCondition(params, DSMCondition::Invite); + + if (cmd == "sessionStart") + return new TestDSMCondition(params, DSMCondition::SessionStart); + ERROR("could not find condition for '%s'\n", cmd.c_str()); return NULL; } @@ -288,6 +294,15 @@ bool SCClosePlaylistAction::execute(AmSession* sess, return false; } +bool SCConnectMediaAction::execute(AmSession* sess, + DSMCondition::EventType event, + map* event_params) { + GET_SCSESSION(); + sc_sess->connectMedia(); + return false; +} + + bool SCStopAction::execute(AmSession* sess, DSMCondition::EventType event, map* event_params) { diff --git a/apps/dsm/DSMCoreModule.h b/apps/dsm/DSMCoreModule.h index 0dfc4fca..db749aa1 100644 --- a/apps/dsm/DSMCoreModule.h +++ b/apps/dsm/DSMCoreModule.h @@ -55,6 +55,7 @@ DEF_SCStrArgAction(SCRecordFileAction); DEF_SCStrArgAction(SCStopRecordAction); DEF_SCStrArgAction(SCClosePlaylistAction); DEF_SCStrArgAction(SCStopAction); +DEF_SCStrArgAction(SCConnectMediaAction); DEF_SCStrArgAction(SCSetPromptsAction); DEF_SCStrArgAction(SCAddSeparatorAction); diff --git a/apps/dsm/DSMDialog.cpp b/apps/dsm/DSMDialog.cpp index b1e00685..1e4a72e9 100644 --- a/apps/dsm/DSMDialog.cpp +++ b/apps/dsm/DSMDialog.cpp @@ -27,6 +27,8 @@ #include "DSMDialog.h" #include "AmUtils.h" +#include "AmMediaProcessor.h" +#include "DSM.h" DSMDialog::DSMDialog(AmPromptCollection& prompts, DSMStateDiagramCollection& diags, @@ -51,9 +53,28 @@ DSMDialog::~DSMDialog() it->second->cleanup((long)this); } +/** returns whether var exists && var==value*/ +bool DSMDialog::checkVar(const string& var_name, const string& var_val) { + map::iterator it = var.find(var_name); + if ((it != var.end()) && (it->second == var_val)) + return false; + + return true; +} + void DSMDialog::onInvite(const AmSipRequest& req) { - engine.onInvite(req, this); - AmSession::onInvite(req); + bool run_session_invite = engine.onInvite(req, this); + + if (DSMFactory::RunInviteEvent) { + if (!engine.init(this, startDiagName, DSMCondition::Invite)) + run_session_invite =false; + + run_session_invite &= + !checkVar(DSM_CONNECT_SESSION, DSM_CONNECT_SESSION_FALSE); + } + + if (run_session_invite) + AmSession::onInvite(req); } void DSMDialog::onSessionStart(const AmSipRequest& req) @@ -69,16 +90,27 @@ void DSMDialog::onSessionStart(const AmSipReply& rep) } void DSMDialog::startSession(){ - engine.init(this, startDiagName); + engine.init(this, startDiagName, DSMCondition::SessionStart); setReceiving(true); + if (checkVar(DSM_CONNECT_SESSION, DSM_CONNECT_SESSION_FALSE)) { + if (!getInput()) + setInput(&playlist); + + setOutput(&playlist); + } +} + +void DSMDialog::connectMedia() { if (!getInput()) setInput(&playlist); setOutput(&playlist); + AmMediaProcessor::instance()->addSession(this, callgroup); } + void DSMDialog::onDtmf(int event, int duration_msec) { DBG("* Got DTMF key %d duration %d\n", event, duration_msec); diff --git a/apps/dsm/DSMDialog.h b/apps/dsm/DSMDialog.h index e6670453..967b1bb7 100644 --- a/apps/dsm/DSMDialog.h +++ b/apps/dsm/DSMDialog.h @@ -51,6 +51,7 @@ class DSMDialog : public AmSession, AmAudioFile* rec_file; map prompt_sets; + bool checkVar(const string& var_name, const string& var_val); public: DSMDialog(AmPromptCollection& prompts, DSMStateDiagramCollection& diags, @@ -81,6 +82,7 @@ public: void setPromptSet(const string& name); void addSeparator(const string& name); + void connectMedia(); }; #endif diff --git a/apps/dsm/DSMModule.h b/apps/dsm/DSMModule.h index e7ffc955..47a1b98f 100644 --- a/apps/dsm/DSMModule.h +++ b/apps/dsm/DSMModule.h @@ -46,7 +46,7 @@ class DSMModule { virtual DSMCondition* getCondition(const string& from_str) = 0; virtual int preload() { return 0; } - virtual void onInvite(const AmSipRequest& req, DSMSession* sess) { } + virtual bool onInvite(const AmSipRequest& req, DSMSession* sess) { return true; } }; typedef void* (*SCFactoryCreate)(); diff --git a/apps/dsm/DSMSession.cpp b/apps/dsm/DSMSession.cpp index 897aef3c..6ba2afbd 100644 --- a/apps/dsm/DSMSession.cpp +++ b/apps/dsm/DSMSession.cpp @@ -27,7 +27,8 @@ #include "DSMSession.h" -DSMSession::DSMSession() { +DSMSession::DSMSession() + : last_req(0) { } DSMSession::~DSMSession() { diff --git a/apps/dsm/DSMSession.h b/apps/dsm/DSMSession.h index 23698344..2c45e649 100644 --- a/apps/dsm/DSMSession.h +++ b/apps/dsm/DSMSession.h @@ -29,6 +29,7 @@ #include "AmArg.h" #include "AmEvent.h" +#include "AmSipMsg.h" #include using std::string; @@ -36,12 +37,19 @@ using std::string; using std::vector; #include using std::map; +#include #define DSM_ERRNO_FILE "1" #define DSM_ERRNO_UNKNOWN_ARG "2" #define DSM_ERRNO_GENERAL "99" #define DSM_ERRNO_OK "" +#define DSM_REPLY_REQUEST "reply_request" // todo: rethink these names +#define DSM_REPLY_REQUEST_FALSE "0" + +#define DSM_CONNECT_SESSION "connect_session" // todo: rethink these names +#define DSM_CONNECT_SESSION_FALSE "0" + #define SET_ERRNO(new_errno) \ var["errno"] = new_errno @@ -58,12 +66,15 @@ class DSMSession { virtual void closePlaylist(bool notify) = 0; virtual void setPromptSet(const string& name) = 0; virtual void addSeparator(const string& name) = 0; - + virtual void connectMedia() = 0; /* holds variables which are accessed by $varname */ map var; /* result of the last DI call */ AmArg di_res; + + /* last received request */ + std::auto_ptr last_req; }; diff --git a/apps/dsm/DSMStateEngine.cpp b/apps/dsm/DSMStateEngine.cpp index b4ecefe4..2d00df24 100644 --- a/apps/dsm/DSMStateEngine.cpp +++ b/apps/dsm/DSMStateEngine.cpp @@ -111,13 +111,15 @@ DSMStateEngine::DSMStateEngine() } DSMStateEngine::~DSMStateEngine() { - } -void DSMStateEngine::onInvite(const AmSipRequest& req, DSMSession* sess) { +bool DSMStateEngine::onInvite(const AmSipRequest& req, DSMSession* sess) { + bool res = true; for (vector::iterator it = mods.begin(); it != mods.end(); it++) - (*it)->onInvite(req, sess); + res &= (*it)->onInvite(req, sess); + + return res; } bool DSMStateEngine::runactions(vector::iterator from, @@ -167,16 +169,17 @@ void DSMStateEngine::addModules(vector modules) { mods.push_back(*it); } -bool DSMStateEngine::init(AmSession* sess, const string& startDiagram) { +bool DSMStateEngine::init(AmSession* sess, const string& startDiagram, + DSMCondition::EventType init_event) { - if (!jumpDiag(startDiagram, sess, DSMCondition::Any, NULL)) { + if (!jumpDiag(startDiagram, sess, init_event, NULL)) { ERROR("initializing with start diag '%s'\n", startDiagram.c_str()); return false; } - DBG("run null event...\n"); - runEvent(sess, DSMCondition::Any, NULL); + DBG("run init event...\n"); + runEvent(sess, init_event, NULL); return true; } diff --git a/apps/dsm/DSMStateEngine.h b/apps/dsm/DSMStateEngine.h index eb21b6fd..6788895a 100644 --- a/apps/dsm/DSMStateEngine.h +++ b/apps/dsm/DSMStateEngine.h @@ -57,6 +57,8 @@ class DSMCondition public: enum EventType { Any, + Invite, + SessionStart, Key, Timer, @@ -174,13 +176,15 @@ class DSMStateEngine { void addDiagram(DSMStateDiagram* diag); void addModules(vector modules); - bool init(AmSession* sess, const string& startDiagram); + bool init(AmSession* sess, const string& startDiagram, + DSMCondition::EventType init_event); void runEvent(AmSession* sess, DSMCondition::EventType event, map* event_params); - void onInvite(const AmSipRequest& req, DSMSession* sess); + /** @return whether call should be accepted */ + bool onInvite(const AmSipRequest& req, DSMSession* sess); }; diff --git a/apps/dsm/doc/dsm_syntax.txt b/apps/dsm/doc/dsm_syntax.txt index a2dc41b9..63373576 100644 --- a/apps/dsm/doc/dsm_syntax.txt +++ b/apps/dsm/doc/dsm_syntax.txt @@ -61,6 +61,7 @@ actions: stop() e.g. stop(false), stop(true) + ============================= conditions: @@ -102,4 +103,16 @@ imports: module load path. modules provide conditions and actions. modules' actions/conditions-factory is checked first (modules can override core conditions/actions) +============================= +special variables: + reply_request "0" ->do not reply to the request as standard behaviour + connect_session "0" ->do not connect session to media processor on start +============================= +errors: + actions set $errno + #define DSM_ERRNO_OK "" + #define DSM_ERRNO_FILE "1" + #define DSM_ERRNO_UNKNOWN_ARG "2" + #define DSM_ERRNO_GENERAL "99" + ... diff --git a/apps/dsm/etc/dsm.conf b/apps/dsm/etc/dsm.conf index 9a8a9a81..a70c9535 100644 --- a/apps/dsm/etc/dsm.conf +++ b/apps/dsm/etc/dsm.conf @@ -23,3 +23,8 @@ load_prompts=/usr/local/etc/sems/etc/dsm_in_prompts.conf,/usr/local/etc/sems/etc # load files with this name (+.conf), e.g. mydomain.conf #load_prompts_sets=mydomain +# if run_invite_event is set to "yes", an "invite" event is run +# before the session is started. can be used e.g. for early media +# of delaying final reply +# +#run_invite_event=yes diff --git a/apps/dsm/mods/mod_uri/ModUri.cpp b/apps/dsm/mods/mod_uri/ModUri.cpp index 02860d25..b2eb1dec 100644 --- a/apps/dsm/mods/mod_uri/ModUri.cpp +++ b/apps/dsm/mods/mod_uri/ModUri.cpp @@ -111,8 +111,9 @@ bool URIParseAction::execute(AmSession* sess, return false; } -void URIModule::onInvite(const AmSipRequest& req, DSMSession* sess) { +bool URIModule::onInvite(const AmSipRequest& req, DSMSession* sess) { sess->var["hdrs"] = req.hdrs; + return true; } CONST_TwoParAction(URIGetHeaderAction, ",", false); diff --git a/apps/dsm/mods/mod_uri/ModUri.h b/apps/dsm/mods/mod_uri/ModUri.h index 507ee43b..0e3f7dd6 100644 --- a/apps/dsm/mods/mod_uri/ModUri.h +++ b/apps/dsm/mods/mod_uri/ModUri.h @@ -38,7 +38,7 @@ class URIModule DSMAction* getAction(const string& from_str); DSMCondition* getCondition(const string& from_str); - void onInvite(const AmSipRequest& req, DSMSession* sess); + bool onInvite(const AmSipRequest& req, DSMSession* sess); }; DEF_TwoParAction(URIParseAction);