From 0ce5e2c3d2120cd57813e1c4bebd20aa2775c819 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Mon, 5 Mar 2007 16:19:58 +0000 Subject: [PATCH] * configuration can be accessed in IVR scripts while they are loaded * pin_collect applications again has two modes: authentication via XMLRPC server, and sending out transfer REFER with PIN in URI * added documentation for pin_collect, and transfer for conference git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@257 8eb893ce-cfd4-0310-b710-fb5ebe64c474 --- .../announce_auth}/Readme.announce_auth | 0 apps/ivr/Ivr.cpp | 54 ++++++++++-------- apps/pin_collect/etc/pin_collect.conf | 11 +++- apps/pin_collect/pin_collect.py | 55 +++++++++++++------ doc/Readme.conference | 31 +++++++++++ doc/Readme.pin_collect | 33 +++++++++++ 6 files changed, 143 insertions(+), 41 deletions(-) rename {doc => apps/examples/announce_auth}/Readme.announce_auth (100%) create mode 100644 doc/Readme.pin_collect diff --git a/doc/Readme.announce_auth b/apps/examples/announce_auth/Readme.announce_auth similarity index 100% rename from doc/Readme.announce_auth rename to apps/examples/announce_auth/Readme.announce_auth diff --git a/apps/ivr/Ivr.cpp b/apps/ivr/Ivr.cpp index af1ccb89..bc35d713 100644 --- a/apps/ivr/Ivr.cpp +++ b/apps/ivr/Ivr.cpp @@ -294,16 +294,43 @@ bool IvrFactory::loadScript(const string& path) { PYLOCK; - PyObject *modName,*mod,*dict, *dlg_class, *config=NULL; - - modName = PyString_FromString(path.c_str()); - mod = PyImport_Import(modName); + PyObject *modName=NULL,*mod=NULL,*dict=NULL,*dlg_class=NULL,*config=NULL; + // load module configuration AmConfigReader cfg; string cfg_file = add2path(AmConfig::ModConfigPath,1,(path + ".conf").c_str()); + if(cfg.loadFile(cfg_file)){ + ERROR("could not load config file at %s\n",cfg_file.c_str()); + goto error2; + } + + config = PyDict_New(); + if(!config){ + ERROR("could not allocate new dict for config\n"); + goto error2; + } + + for(map::const_iterator it = cfg.begin(); + it != cfg.end(); it++){ + PyDict_SetItem(config, + PyString_FromString(it->first.c_str()), + PyString_FromString(it->second.c_str())); + } + + // set config ivr ivr_module while loading + Py_INCREF(config); + PyObject_SetAttrString(ivr_module,"config",config); + + // load module + modName = PyString_FromString(path.c_str()); + mod = PyImport_Import(modName); Py_DECREF(modName); + // remove config ivr ivr_module while loading + PyObject_DelAttrString(ivr_module, "config"); + Py_DECREF(config); + if(!mod){ PyErr_Print(); WARN("IvrFactory: Failed to load \"%s\"\n", path.c_str()); @@ -335,25 +362,6 @@ bool IvrFactory::loadScript(const string& path) goto error2; } - if(cfg.loadFile(cfg_file)){ - ERROR("could not load config file at %s\n",cfg_file.c_str()); - goto error2; - } - - config = PyDict_New(); - if(!config){ - ERROR("could not allocate new dict for config\n"); - goto error2; - } - - for(map::const_iterator it = cfg.begin(); - it != cfg.end(); it++){ - - PyDict_SetItem(config, - PyString_FromString(it->first.c_str()), - PyString_FromString(it->second.c_str())); - } - PyObject_SetAttrString(mod,"config",config); mod_reg.insert(make_pair(path, diff --git a/apps/pin_collect/etc/pin_collect.conf b/apps/pin_collect/etc/pin_collect.conf index 5bfbe95c..b270bf44 100644 --- a/apps/pin_collect/etc/pin_collect.conf +++ b/apps/pin_collect/etc/pin_collect.conf @@ -1,6 +1,15 @@ + +# authentication mode: +# XMLRPC : authenticate against XMLRPC server +# REFER : add pin to REFER sent out to be checked at proxy +auth_mode=XMLRPC + +# XMLRPC url to authenticate against if auth_mode==XMLRPC +auth_xmlrpc_url = http://127.0.0.1:9090/ + +# messages to play to caller welcome_msg=/usr/lib/sems/audio/pincollect/welcome.wav pin_msg=/usr/lib/sems/audio/pincollect/enter_pin.wav fail_msg=/usr/lib/sems/audio/pincollect/fail.wav auth_fail_msg=/usr/lib/sems/audio/pincollect/notcorrect.wav -auth_xmlrpc_url = http://127.0.0.1:9090/ \ No newline at end of file diff --git a/apps/pin_collect/pin_collect.py b/apps/pin_collect/pin_collect.py index 9a55c467..a2c10c8f 100644 --- a/apps/pin_collect/pin_collect.py +++ b/apps/pin_collect/pin_collect.py @@ -1,6 +1,8 @@ from log import * from ivr import * -import xmlrpclib + +if (config['auth_mode'] == 'XMLRPC'): + import xmlrpclib #states collect = 0 @@ -64,31 +66,50 @@ class IvrDialog(IvrDialogBase): def onDtmf(self,key,duration): if self.state == collect: + self.flush() if key < 10: self.keys += str(key) debug("added key, PIN = " + self.keys) self.setTimer(HINT_TIMER, HINT_TIMEOUT) elif key == 10: - - c = xmlrpclib.ServerProxy(config['auth_xmlrpc_url']) - erg = c.authorize(self.dialog.user, self.keys) - - debug('result of authentication: '+ str(erg)) - if erg == 'OK': + # XMLRPC authentication mode + if (config['auth_mode'] == 'XMLRPC'): + try: + c = xmlrpclib.ServerProxy(config['auth_xmlrpc_url']) + erg = c.authorize(self.dialog.user, self.keys) + + debug('result of authentication: '+ str(erg)) + if erg == 'OK': + self.state = connect + self.removeTimer(HINT_TIMER) + self.dlg_remote_uri = self.dialog.remote_uri + debug("saved remote_uri "+ self.dlg_remote_uri) + self.transfer_cseq = self.dialog.cseq + self.redirect("sip:" + self.dialog.user + "@" + \ + self.dialog.domain) + else: + self.flush() + self.keys = '' + if self.auth_fail_msg == None: + self.auth_fail_msg = IvrAudioFile() + self.auth_fail_msg.open(config['auth_fail_msg'],AUDIO_READ) + self.enqueue(self.auth_fail_msg,None) + except: + self.dlg_remote_uri = self.dialog.remote_uri + self.state = connect_failed + self.fail_msg = IvrAudioFile() + self.fail_msg.open(config['fail_msg'],AUDIO_READ) + self.enqueue(self.fail_msg,None) + + else: self.state = connect self.removeTimer(HINT_TIMER) - self.dlg_remote_uri = self.dialog.remote_uri + self.dlg_remote_uri = self.dialog.remote_uri debug("saved remote_uri "+ self.dlg_remote_uri) self.transfer_cseq = self.dialog.cseq - self.redirect("sip:" + self.dialog.user + "@" + \ - self.dialog.domain) - else: - self.flush() - self.keys = '' - if self.auth_fail_msg == None: - self.auth_fail_msg = IvrAudioFile() - self.auth_fail_msg.open(config['auth_fail_msg'],AUDIO_READ) - self.enqueue(self.auth_fail_msg,None) + self.redirect("sip:" + self.dialog.user + "+" + self.keys + "@" + \ + self.dialog.domain) + def onEmptyQueue(self): diff --git a/doc/Readme.conference b/doc/Readme.conference index 3148e0e6..60b5b97f 100644 --- a/doc/Readme.conference +++ b/doc/Readme.conference @@ -41,3 +41,34 @@ drop_sound: sound to be played to all the participants dialout_suffix: suffix to be append to the numbered entered by the user. Example: @iptel.org + +Adding participants with "Transfer" REFER: +------------------------------------------ + The "Transfer REFER" is a proprietary REFER call flow which transfers a + SIP dialog and session to another user agent ('taker'). If the transfer + REFER is accepted, the one transfering the call just "forgets" the dialog + and associated session, while the taker can send a re-Invite, thus overtaking + the dialog and session. For this to work, both transferer and taker must + be behind the same record routing proxy, and the callers user agent must + properly support re-Invite (updating of contact, and session, as specified + in RFC3261). + + The transfer request sent out has two headers, which are needed by the + entity taking the call: + P-Transfer-RR : route set of the call + P-Transfer-NH : next hop + + These headers must be configured in ser.cfg to be passed to the conference + application, for example using the following tw_append: + + # appends for REFER + modparam( "tm", "tw_append", + "refer_append:hdr[P-Transfer-NH];hdr[P-Transfer-RR]") + + ... + + t_write_unix("/tmp/msp_conference_sock","conference/refer_append"); + + Note that while this request has the method 'REFER', it does not follow rfc3515, + for example the Refer-To header is not used. + diff --git a/doc/Readme.pin_collect b/doc/Readme.pin_collect new file mode 100644 index 00000000..1a6604a1 --- /dev/null +++ b/doc/Readme.pin_collect @@ -0,0 +1,33 @@ +SEMS pin_collect application Readme + +This application collects a PIN and then transfers using a +(proprietary) REFER the call. + +The authentication mode can be set in the configuration file +(auth_mode parameter). + +Authentication Modes: + XMLRPC : Authenticate against an XMLRPC server (python example + server in test/authserver.py + + REFER : the transfer request (REFER) sent out has as user part of + the URI the original user part, a plus sign, and the entered + PIN. The PIN can thus be verified by the proxy handling the + transfer REFER. + + +"Transfer" REFER: + The "Transfer REFER" is a proprietary REFER call flow which transfers a + SIP dialog and session to another user agent ('taker'). If the transfer + REFER is accepted, the one transfering the call just "forgets" the dialog + and associated session, while the taker can send a re-Invite, thus overtaking + the dialog and session. For this to work, both transferer and taker must + be behind the same record routing proxy, and the callers user agent must + properly support re-Invite (updating of contact, and session, as specified + in RFC3261). + + The transfer request sent out has two headers, which are needed by the + entity taking the call: + P-Transfer-RR : route set of the call + P-Transfer-NH : next hop +