mirror of https://github.com/sipwise/sems.git
Thanks goes to Alexandr Dubovikov <shurik@start4.info>. git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@23 8eb893ce-cfd4-0310-b710-fb5ebe64c474sayer/1.4-spce2.6
parent
555dd79d0a
commit
b3e1c37cbd
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* $Id: Announcement.cpp,v 1.7.8.4 2005/08/31 13:54:29 rco Exp $
|
||||
*
|
||||
* Copyright (C) 2002-2003 Fhg Fokus
|
||||
*
|
||||
* 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 "Announcement.h"
|
||||
#include "AmConfig.h"
|
||||
#include "AmUtils.h"
|
||||
#include "AmSessionScheduler.h"
|
||||
|
||||
#include "sems.h"
|
||||
#include "log.h"
|
||||
|
||||
#define MOD_NAME "early_announce"
|
||||
|
||||
EXPORT_SESSION_FACTORY(AnnouncementFactory,MOD_NAME);
|
||||
|
||||
string AnnouncementFactory::AnnouncePath;
|
||||
string AnnouncementFactory::AnnounceFile;
|
||||
|
||||
AnnouncementFactory::AnnouncementFactory(const string& _app_name)
|
||||
: AmSessionFactory(_app_name)
|
||||
{
|
||||
}
|
||||
|
||||
int AnnouncementFactory::onLoad()
|
||||
{
|
||||
AmConfigReader cfg;
|
||||
if(cfg.loadFile(AmConfig::ModConfigPath + string(MOD_NAME ".conf")))
|
||||
return -1;
|
||||
|
||||
// get application specific global parameters
|
||||
configureModule(cfg);
|
||||
|
||||
AnnouncePath = cfg.getParameter("announce_path",ANNOUNCE_PATH);
|
||||
if( !AnnouncePath.empty()
|
||||
&& AnnouncePath[AnnouncePath.length()-1] != '/' )
|
||||
AnnouncePath += "/";
|
||||
|
||||
AnnounceFile = cfg.getParameter("default_announce",ANNOUNCE_FILE);
|
||||
|
||||
string announce_file = AnnouncePath + AnnounceFile;
|
||||
if(!file_exists(announce_file)){
|
||||
ERROR("default file for ann_b2b module does not exist ('%s').\n",
|
||||
announce_file.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void AnnouncementDialog::onInvite(const AmSipRequest& req)
|
||||
{
|
||||
string sdp_reply;
|
||||
if(acceptAudio(req,sdp_reply)!=0)
|
||||
return;
|
||||
|
||||
if(dlg.reply(req,183,"Session Progress",
|
||||
"application/sdp",sdp_reply) != 0){
|
||||
|
||||
//throw AmSession::Exception(500,"error while sending response");
|
||||
setStopped();
|
||||
}
|
||||
else {
|
||||
|
||||
localreq = req;
|
||||
}
|
||||
|
||||
// reply_code = 183; // early dialog
|
||||
// reply_reason = "Session Progress";
|
||||
|
||||
}
|
||||
|
||||
|
||||
AmSession* AnnouncementFactory::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))
|
||||
goto end;
|
||||
|
||||
announce_file = announce_path + req.user + ".wav";
|
||||
DBG("trying '%s'\n",announce_file.c_str());
|
||||
if(file_exists(announce_file))
|
||||
goto end;
|
||||
|
||||
announce_file = AnnouncePath + AnnounceFile;
|
||||
|
||||
end:
|
||||
return new AnnouncementDialog(announce_file);
|
||||
}
|
||||
|
||||
AnnouncementDialog::AnnouncementDialog(const string& filename)
|
||||
: filename(filename)
|
||||
{
|
||||
}
|
||||
|
||||
AnnouncementDialog::~AnnouncementDialog()
|
||||
{
|
||||
}
|
||||
|
||||
void AnnouncementDialog::onSessionStart(const AmSipRequest& req)
|
||||
{
|
||||
DBG("AnnouncementDialog::onSessionStart\n");
|
||||
if(wav_file.open(filename,AmAudioFile::Read))
|
||||
throw string("AnnouncementDialog::onSessionStart: Cannot open file\n");
|
||||
|
||||
setOutput(&wav_file);
|
||||
}
|
||||
|
||||
void AnnouncementDialog::onBye(const AmSipRequest& req)
|
||||
{
|
||||
DBG("onBye: stopSession\n");
|
||||
setStopped();
|
||||
}
|
||||
|
||||
void AnnouncementDialog::onCancel()
|
||||
{
|
||||
dlg.reply(localreq,487,"Call terminated");
|
||||
setStopped();
|
||||
}
|
||||
|
||||
void AnnouncementDialog::process(AmEvent* event)
|
||||
{
|
||||
|
||||
AmAudioEvent* audio_event = dynamic_cast<AmAudioEvent*>(event);
|
||||
if(audio_event)
|
||||
{
|
||||
switch(audio_event->event_id)
|
||||
{
|
||||
|
||||
case AmAudioEvent::cleared:
|
||||
DBG("AmAudioEvent::cleared\n");
|
||||
//dlg.bye();
|
||||
setStopped();
|
||||
return;
|
||||
break;
|
||||
|
||||
case AmAudioEvent::noAudio:
|
||||
DBG("AmAudioEvent::noAudio\n");
|
||||
unsigned int code_i;
|
||||
string code = getHeader(localreq.hdrs,"P-Final-Reply-Code");
|
||||
string reason = getHeader(localreq.hdrs,"P-Final-Reply-Reason");
|
||||
|
||||
if (code.length() && reason.length() && !str2i(code, code_i) ) {
|
||||
DBG("Replying with code %d %s\n", code_i, reason.c_str());
|
||||
dlg.reply(localreq, code_i, reason);
|
||||
} else {
|
||||
DBG("Replying with std code 404 Not found\n");
|
||||
dlg.reply(localreq, 404, "Not Found");
|
||||
}
|
||||
setStopped();
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AmSession::process(event);
|
||||
}
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* $Id: Announcement.h,v 1.6.8.1 2005/06/01 12:00:24 rco Exp $
|
||||
*
|
||||
* Copyright (C) 2002-2003 Fhg Fokus
|
||||
*
|
||||
* 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 _ANNOUNCEMENT_H_
|
||||
#define _ANNOUNCEMENT_H_
|
||||
|
||||
#include "AmSession.h"
|
||||
#include "AmConfigReader.h"
|
||||
|
||||
#include <string>
|
||||
using std::string;
|
||||
|
||||
class AnnouncementFactory: public AmSessionFactory
|
||||
{
|
||||
public:
|
||||
static string AnnouncePath;
|
||||
static string AnnounceFile;
|
||||
|
||||
AnnouncementFactory(const string& _app_name);
|
||||
|
||||
int onLoad();
|
||||
AmSession* onInvite(const AmSipRequest& req);
|
||||
};
|
||||
|
||||
class AnnouncementDialog : public AmSession
|
||||
{
|
||||
AmAudioFile wav_file;
|
||||
string filename;
|
||||
AmSipRequest localreq;
|
||||
|
||||
public:
|
||||
AnnouncementDialog(const string& filename);
|
||||
~AnnouncementDialog();
|
||||
|
||||
void onInvite(const AmSipRequest& req);
|
||||
void onSessionStart(const AmSipRequest& req);
|
||||
void onBye(const AmSipRequest& req);
|
||||
void onCancel();
|
||||
void onDtmf(int event, int duration_msec) {}
|
||||
|
||||
void process(AmEvent* event);
|
||||
};
|
||||
|
||||
#endif
|
||||
// Local Variables:
|
||||
// mode:C++
|
||||
// End:
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
plug_in_name = early_announce
|
||||
|
||||
module_ldflags =
|
||||
module_cflags =
|
||||
|
||||
COREPATH ?=../../core
|
||||
include $(COREPATH)/plug-in/Makefile.app_module
|
||||
@ -0,0 +1,141 @@
|
||||
************************************
|
||||
* Early announcement Server Module *
|
||||
************************************
|
||||
|
||||
Description:
|
||||
------------
|
||||
|
||||
The annoucement server plays a wav file to the caller
|
||||
in an early session: it replies to an invite with
|
||||
183 Session Progress (with SDP), then sends the announcement
|
||||
and finally replies the request with a response (by default
|
||||
404 Not found ).
|
||||
|
||||
Additional Headers:
|
||||
P-Final-Reply-Code integer (ex. P-Final-Reply-Code:405 )
|
||||
P-Final-Reply-Reason string (e.g. P-Final-Reply-Reason:Prohibited)
|
||||
|
||||
|
||||
It searches for files to play following these rules:
|
||||
|
||||
1) [AnnouncePath]/[Domain]/[User].wav
|
||||
2) [AnnouncePath]/[User].wav
|
||||
|
||||
example sems (early_announce.conf) configuration:
|
||||
|
||||
announce_path=wav/
|
||||
default_announce=default_en.wav
|
||||
|
||||
|
||||
example ser configuration:
|
||||
|
||||
#
|
||||
# simple single instance Ser config script with early media
|
||||
# ----------- global configuration parameters ------------------------
|
||||
|
||||
debug=5 # debug level (cmd line: -dddddddddd)
|
||||
fork=yes
|
||||
log_stderror=yes # (cmd line: -E)
|
||||
|
||||
check_via=no # (cmd. line: -v)
|
||||
dns=no # (cmd. line: -r)
|
||||
rev_dns=no # (cmd. line: -R)
|
||||
port=5060
|
||||
#children=4
|
||||
sip_warning=no
|
||||
|
||||
# Configure Ser to create a FIFO server
|
||||
#fifo="/tmp/ser_fifo"
|
||||
|
||||
# Configure Ser to create an unix socket server
|
||||
unix_sock="/tmp/ser_socket"
|
||||
|
||||
loadmodule "modules/sl/sl.so"
|
||||
loadmodule "modules/tm/tm.so"
|
||||
loadmodule "modules/rr/rr.so"
|
||||
loadmodule "modules/maxfwd/maxfwd.so"
|
||||
loadmodule "modules/avp/avp.so"
|
||||
loadmodule "modules/avpops/avpops.so"
|
||||
|
||||
# -- rr params --
|
||||
# add value to ;lr param to make some broken UAs happy
|
||||
modparam("rr", "enable_full_lr", 1)
|
||||
|
||||
modparam( "avpops", "avp_aliases", "early_code=i:66 ; early_reason=i:67" )
|
||||
|
||||
# this is to be appended to the invite
|
||||
modparam("tm", "tw_append","early_headers:P-Final-Reply-Code=avp[$early_code];P-Final-Reply-Reason=avp[$early_reason]")
|
||||
|
||||
# ------------------------- request routing logic -------------------
|
||||
# main routing logic
|
||||
route{
|
||||
|
||||
# initial sanity checks -- messages with
|
||||
# max_forwards==0, or excessively long requests
|
||||
if (!mf_process_maxfwd_header("10")) {
|
||||
sl_send_reply("483","Too Many Hops");
|
||||
break;
|
||||
};
|
||||
if ( msg:len > max_len ) {
|
||||
sl_send_reply("513", "Message too big");
|
||||
break;
|
||||
};
|
||||
# we record-route all messages -- to make sure that
|
||||
# subsequent messages will go through our proxy; that's
|
||||
# particularly good if upstream and downstream entities
|
||||
# use different transport protocol
|
||||
record_route();
|
||||
# loose-route processing
|
||||
if (loose_route()) {
|
||||
t_relay();
|
||||
break;
|
||||
};
|
||||
|
||||
if (uri==myself) {
|
||||
# filter unsupported requests
|
||||
if (!(method=="REGISTER" || method=="ACK" || method=="INVITE" ||
|
||||
method=="BYE" || method=="CANCEL" )) {
|
||||
sl_send_reply("501", "method not understood here");
|
||||
break;
|
||||
}
|
||||
|
||||
if (method=="REGISTER") {
|
||||
# make UAs which want to register unhappy
|
||||
sl_send_reply("501","registration couldn't be accepted");
|
||||
break;
|
||||
};
|
||||
|
||||
if (!t_newtran()){
|
||||
sl_send_reply("500","could not create transaction");
|
||||
break;
|
||||
};
|
||||
|
||||
if (method == "INVITE") {
|
||||
|
||||
avp_write("405", "$early_code");
|
||||
avp_write("Prohiboted", "$early_reason");
|
||||
|
||||
if(!t_write_unix("/tmp/sems_sock","early_announce/early_headers")){
|
||||
log("could not contact early_announce\n");
|
||||
t_reply("404","not found");
|
||||
};
|
||||
break;
|
||||
|
||||
} else if (method=="BYE" || method=="CANCEL") {
|
||||
if(!t_write_unix("/tmp/sems_sock","bye")) {
|
||||
t_reply("500","error contacting sems");
|
||||
};
|
||||
break;
|
||||
} else if (method=="ACK"){
|
||||
# absorb ACKs
|
||||
t_relay();
|
||||
break;
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
if (!t_relay()) {
|
||||
sl_reply_error();
|
||||
};
|
||||
}
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
#CFGOPTION_SEMS_ANNOUNCEPATH
|
||||
announce_path=wav/
|
||||
#ENDCFGOPTION
|
||||
|
||||
#CFGOPTION_SEMS_ANNOUNCEMENT
|
||||
default_announce=default_en.wav
|
||||
#ENDCFGOPTION
|
||||
Loading…
Reference in new issue