serviceline application - ivr, then auth'ed b2b call with media relay

git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@447 8eb893ce-cfd4-0310-b710-fb5ebe64c474
sayer/1.4-spce2.6
Stefan Sayer 19 years ago
parent 17d20f3c56
commit f5d9f0cfe5

@ -0,0 +1,10 @@
plug_in_name = serviceline
module_ldflags =
module_cflags =
extra_install = $(plug_in_name)_audio
COREPATH ?=../../../core
include $(COREPATH)/plug-in/Makefile.app_module

@ -0,0 +1,19 @@
serviceline application
This application could serve for something like a service line:
The caller calls the service number, and gets an ivr menu, from where
she can be connected to various numbers - by pressing 0 she is connected
to one number, by pressing 1 to another number etc.
The outgoing call is connected in B2BUA mode with media relay ('b2abua'),
so technically the two legs are independent sip dialogs and media sessions.
The outgoing calls (B leg) are optionally SIP authenticated, so for example,
normal gateways can be used. The uac_auth module must be loaded for this
to work. If the uac_auth module is not loaded, the outgoing calls are not
authenticated.
To extend this module with so useful things like prompt on failed call,
leave message fwdd via email on failed call etc is left as an exercise
to the reader. Improvements are of course welcome as svn diff to the
semsdev mailing list.

@ -0,0 +1,205 @@
/*
* $Id: ServiceLine.cpp 433 2007-08-29 20:17:38Z sayer $
*
* Copyright (C) 2007 iptego GmbH
*
* This file is part of SEMS, a free SIP media server.
*
* SEMS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* For a license to use the SEMS software under conditions
* other than those described here, or to purchase support for this
* software, please contact iptel.org by e-mail at the following addresses:
* info@iptel.org
*
* SEMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ServiceLine.h"
#include "AmSessionContainer.h"
#include "AmConfig.h"
#include "AmUtils.h"
#include "AmApi.h"
#include "AmPlugIn.h"
#include "AmMediaProcessor.h"
#include "sems.h"
#include "log.h"
#define MOD_NAME "serviceline"
EXPORT_SESSION_FACTORY(ServiceLineFactory,MOD_NAME);
string ServiceLineFactory::AnnouncePath;
string ServiceLineFactory::AnnounceFile;
string ServiceLineFactory::callee_numbers[10];
string ServiceLineFactory::GWDomain;
string ServiceLineFactory::GWUser;
string ServiceLineFactory::GWDisplayname;
string ServiceLineFactory::GWAuthuser;
string ServiceLineFactory::GWAuthrealm;
string ServiceLineFactory::GWAuthpwd;
ServiceLineFactory::ServiceLineFactory(const string& _app_name)
: AmSessionFactory(_app_name)
{
}
int ServiceLineFactory::onLoad()
{
AmConfigReader cfg;
if(cfg.loadFile(AmConfig::ModConfigPath + string(MOD_NAME ".conf")))
return -1;
// get application specific global parameters
configureModule(cfg);
AnnounceFile = cfg.getParameter("prompt",ANNOUNCE_FILE);
DBG("Prompt = %s\n",AnnounceFile.c_str());
string announce_file = AnnounceFile;
if(!file_exists(announce_file)){
ERROR("prompt file for serviceline module does not exist ('%s').\n",
announce_file.c_str());
return -1;
}
DBG("ServiceLine Connect DTMF Key Mapping:\n");
for (unsigned int i=0;i<10;i++) {
callee_numbers[i] = cfg.getParameter("callee_number"+int2str(i));
DBG("Key %u -> Extension __%s__\n",
i, callee_numbers[i].empty()?
"none":callee_numbers[i].c_str());
}
GWDomain= cfg.getParameter("gw_domain", "");;
GWUser= cfg.getParameter("gw_user", "");;
GWDisplayname= cfg.getParameter("gw_displayname", "");;
GWAuthuser= cfg.getParameter("gw_authuser", "");
GWAuthrealm=cfg.getParameter("gw_authrealm", ""); // actually unused
GWAuthpwd=cfg.getParameter("gw_authpwd", "");
return 0;
}
AmSession* ServiceLineFactory::onInvite(const AmSipRequest& req)
{
string announce_path = AnnouncePath;
string announce_file = announce_path + req.domain
+ "/" + req.user + ".wav";
DBG("trying '%s'\n",announce_file.c_str());
if(file_exists(announce_file))
new ServiceLineCallerDialog(announce_file);
announce_file = announce_path + req.user + ".wav";
DBG("trying '%s'\n",announce_file.c_str());
if(file_exists(announce_file))
new ServiceLineCallerDialog(announce_file);
announce_file = AnnouncePath + AnnounceFile;
return new ServiceLineCallerDialog(announce_file);
}
ServiceLineCallerDialog::ServiceLineCallerDialog(const string& filename)
: filename(filename),
playlist(this),
AmB2ABCallerSession()
{
}
void ServiceLineCallerDialog::onSessionStart(const AmSipRequest& req)
{
AmB2ABCallerSession::onSessionStart(req);
if(wav_file.open(filename,AmAudioFile::Read))
throw string("AnnouncementDialog::onSessionStart: Cannot open file\n");
setInOut(&playlist, &playlist);
playlist.addToPlaylist(new AmPlaylistItem(&wav_file, NULL));
}
void ServiceLineCallerDialog::process(AmEvent* event)
{
AmAudioEvent* audio_event = dynamic_cast<AmAudioEvent*>(event);
if(audio_event && (audio_event->event_id == AmAudioEvent::cleared)){
DBG("ignoring end of prompt.\n");
return;
}
AmB2ABCallerSession::process(event);
}
void ServiceLineCallerDialog::onDtmf(int event, int duration)
{
DBG("DTMF event %d duration %d\n", event, duration);
if (getCalleeStatus() != None)
return;
if ((event < 10) && (event >= 0) &&
(!ServiceLineFactory::callee_numbers[event].empty())) {
connectCallee("sip:"+ServiceLineFactory::callee_numbers[event]+"@"+ServiceLineFactory::GWDomain,
"sip:"+ServiceLineFactory::callee_numbers[event]+"@"+ServiceLineFactory::GWDomain,
"sip:"+ServiceLineFactory::GWUser+"@"+ServiceLineFactory::GWDomain,
"sip:"+ServiceLineFactory::GWUser+"@"+ServiceLineFactory::GWDomain);
}
return;
}
AmB2ABCalleeSession* ServiceLineCallerDialog::createCalleeSession() {
ServiceLineCalleeDialog* sess = new ServiceLineCalleeDialog(getLocalTag());
AmSessionEventHandlerFactory* uac_auth_f =
AmPlugIn::instance()->getFactory4Seh("uac_auth");
if (NULL != uac_auth_f) {
DBG("UAC Auth enabled for new serviceline session.\n");
AmSessionEventHandler* h = uac_auth_f->getHandler(sess);
if (h != NULL )
sess->addHandler(h);
else {
ERROR("unable to set SIP UAC auth for new session.");
}
} else {
ERROR("unable to get SIP UAC auth."
"(uac_auth module loaded?)\n");
}
return sess;
}
ServiceLineCalleeDialog::~ServiceLineCalleeDialog() {
}
ServiceLineCalleeDialog::ServiceLineCalleeDialog(const string& other_tag)
: AmB2ABCalleeSession(other_tag),
cred(ServiceLineFactory::GWAuthrealm,
ServiceLineFactory::GWAuthuser,
ServiceLineFactory::GWAuthpwd)
{
rtp_str.setPlayoutType(ADAPTIVE_PLAYOUT);
setDtmfDetectionEnabled(false);
}
UACAuthCred* ServiceLineCalleeDialog::getCredentials() {
return &cred;
}

@ -0,0 +1,99 @@
/*
* $Id: ServiceLine.h 433 2007-08-29 20:17:38Z sayer $
*
* Copyright (C) 2007 iptego GmbH
*
* This file is part of SEMS, a free SIP media server.
*
* SEMS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* For a license to use the SEMS software under conditions
* other than those described here, or to purchase support for this
* software, please contact iptel.org by e-mail at the following addresses:
* info@iptel.org
*
* SEMS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _SERVICELINE_H_
#define _SERVICELINE_H_
#include "AmApi.h"
#include "AmConfigReader.h"
#include "AmAudio.h"
#include "AmB2ABSession.h"
#include "ampi/UACAuthAPI.h"
#include <string>
using std::string;
class ServiceLineFactory: public AmSessionFactory
{
public:
static string AnnouncePath;
static string AnnounceFile;
static string callee_numbers[10];
static string GWDomain;
static string GWUser;
static string GWDisplayname;
static string GWAuthuser;
static string GWAuthrealm;
static string GWAuthpwd;
ServiceLineFactory(const string& _app_name);
int onLoad();
AmSession* onInvite(const AmSipRequest& req);
};
class ServiceLineCallerDialog: public AmB2ABCallerSession
{
AmAudioFile wav_file;
// we use a playlist to keep media processing, RTP
// sending & DTMF detection after prompt has finished
AmPlaylist playlist;
string filename;
string callee_addr;
string callee_uri;
public:
ServiceLineCallerDialog(const string& filename);
void process(AmEvent* event);
void onDtmf(int event, int duration);
void onSessionStart(const AmSipRequest& req);
virtual AmB2ABCalleeSession* createCalleeSession();
};
// need this for auth
class ServiceLineCalleeDialog
: public AmB2ABCalleeSession,
public CredentialHolder {
UACAuthCred cred;
public:
ServiceLineCalleeDialog(const string& other_tag);
~ServiceLineCalleeDialog();
UACAuthCred* getCredentials();
};
#endif
// Local Variables:
// mode:C++
// End:

@ -0,0 +1,21 @@
# the prompt that is played at the beginning
# ("press one to connect to x, two for y, ..."
prompt=/usr/local/lib/sems/audio/default_en.wav
# 0 pressed -> call callee_number0@gw_domain
# 1 pressed -> call callee_number1@gw_domain
# etc.
callee_number0=+49123456789
callee_number1=+34222222222
# domain/gateway used for outgoing calls (B leg)
#
gw_domain=myprovider.com
gw_user=myuser
gw_displayname=myuser
# authentication (if needed)
gw_authuser=my_auth_user
gw_authrealm=myprovider.com
gw_authpwd=verysecret
Loading…
Cancel
Save