b3e1c37c |
/*
|
6d8f8d96 |
* $Id$
|
b3e1c37c |
*
* Copyright (C) 2002-2003 Fhg Fokus
|
a15202f0 |
* Copyright (C) 2008 Juha Heinanen (USE_MYSQL parts)
|
b3e1c37c |
*
* 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
*/
|
1f5be2af |
#include "EarlyAnnounce.h"
|
b3e1c37c |
#include "AmConfig.h"
#include "AmUtils.h"
#include "sems.h"
#include "log.h"
#define MOD_NAME "early_announce"
|
a15202f0 |
#ifdef USE_MYSQL
#include <mysql++/mysql++.h>
#include <stdio.h>
#define DEFAULT_AUDIO_TABLE "default_audio"
#define DOMAIN_AUDIO_TABLE "domain_audio"
#define USER_AUDIO_TABLE "user_audio"
#endif
|
1f5be2af |
EXPORT_SESSION_FACTORY(EarlyAnnounceFactory,MOD_NAME);
|
b3e1c37c |
|
a15202f0 |
#ifdef USE_MYSQL
string EarlyAnnounceFactory::AnnounceApplication;
string EarlyAnnounceFactory::AnnounceMessage;
string EarlyAnnounceFactory::DefaultLanguage;
#else
|
1f5be2af |
string EarlyAnnounceFactory::AnnouncePath;
string EarlyAnnounceFactory::AnnounceFile;
|
a15202f0 |
#endif
|
b3e1c37c |
|
94a0733f |
EarlyAnnounceFactory::ContB2B EarlyAnnounceFactory::ContinueB2B =
EarlyAnnounceFactory::Never;
|
7dac246b |
|
1f5be2af |
EarlyAnnounceFactory::EarlyAnnounceFactory(const string& _app_name)
|
b3e1c37c |
: AmSessionFactory(_app_name)
{
}
|
a15202f0 |
#ifdef USE_MYSQL
mysqlpp::Connection EarlyAnnounceFactory::Connection(mysqlpp::use_exceptions);
int get_announce_msg(string application, string message, string user,
string domain, string language, string *audio_file)
{
string query_string;
if (!user.empty()) {
*audio_file = string("/tmp/") + application + "_" +
message + "_" + domain + "_" + user + ".wav";
query_string = "select audio from " + string(USER_AUDIO_TABLE) +
" where application='" + application + "' and message='" +
message + "' and userid='" + user + "' and domain='" +
domain + "'";
} else if (!domain.empty()) {
*audio_file = string("/tmp/") + application + "_" +
message + "_" + domain + "_" + language + ".wav";
query_string = "select audio from " + string(DOMAIN_AUDIO_TABLE) +
" where application='" + application + "' and message='" +
message + "' and domain='" + domain + "' and language='" +
language + "'";
} else {
*audio_file = string("/tmp/") + application + "_" +
message + "_" + language + ".wav";
query_string = "select audio from " + string(DEFAULT_AUDIO_TABLE) +
" where application='" + application + "' and message='" +
message + "' and language='" + language + "'";
}
try {
mysqlpp::Query query = EarlyAnnounceFactory::Connection.query();
DBG("Query string <%s>\n", query_string.c_str());
query << query_string;
|
ffe99681 |
#ifdef VERSION2
|
a15202f0 |
mysqlpp::Result res = query.store();
|
ffe99681 |
#else
mysqlpp::StoreQueryResult res = query.store();
#endif
|
a15202f0 |
mysqlpp::Row row;
if (res) {
if ((res.num_rows() > 0) && (row = res.at(0))) {
FILE *file;
file = fopen((*audio_file).c_str(), "wb");
|
ffe99681 |
#ifdef VERSION2
unsigned long length = row.raw_string(0).size();
|
a15202f0 |
fwrite(row.at(0).data(), 1, length, file);
|
ffe99681 |
#else
mysqlpp::String s = row[0];
fwrite(s.data(), 1, s.length(), file);
#endif
|
a15202f0 |
fclose(file);
return 1;
} else {
*audio_file = "";
return 1;
}
} else {
ERROR("Database query error\n");
*audio_file = "";
return 0;
}
}
catch (const mysqlpp::Exception& er) {
// Catch-all for any MySQL++ exceptions
ERROR("MySQL++ error: %s\n", er.what());
*audio_file = "";
return 0;
}
}
#endif
|
1f5be2af |
int EarlyAnnounceFactory::onLoad()
|
b3e1c37c |
{
|
8d76c8bb |
AmConfigReader cfg;
if(cfg.loadFile(AmConfig::ModConfigPath + string(MOD_NAME ".conf")))
return -1;
|
b3e1c37c |
|
8d76c8bb |
// get application specific global parameters
configureModule(cfg);
|
b3e1c37c |
|
94a0733f |
if (cfg.hasParameter("continue_b2b")) {
if (cfg.getParameter("continue_b2b") == "yes") {
ContinueB2B = Always;
DBG("early_announce in b2bua mode.\n");
}
else if (cfg.getParameter("continue_b2b") == "app-param") {
ContinueB2B = AppParam;
DBG("early_announce in b2bua/final reply mode "
"(depends on app-param).\n");
} else {
DBG("early_announce sends final reply.\n");
}
|
7dac246b |
}
|
a15202f0 |
#ifdef USE_MYSQL
/* Get default audio from MySQL */
string mysql_server, mysql_user, mysql_passwd, mysql_db;
mysql_server = cfg.getParameter("mysql_server");
if (mysql_server.empty()) {
mysql_server = "localhost";
}
mysql_user = cfg.getParameter("mysql_user");
if (mysql_user.empty()) {
|
c30c0217 |
ERROR("conference.conf parameter 'mysql_user' is missing.\n");
|
a15202f0 |
return -1;
}
mysql_passwd = cfg.getParameter("mysql_passwd");
if (mysql_passwd.empty()) {
|
c30c0217 |
ERROR("conference.conf parameter 'mysql_passwd' is missing.\n");
|
a15202f0 |
return -1;
}
mysql_db = cfg.getParameter("mysql_db");
if (mysql_db.empty()) {
mysql_db = "sems";
}
AnnounceApplication = cfg.getParameter("application");
if (AnnounceApplication.empty()) {
AnnounceApplication = MOD_NAME;
}
AnnounceMessage = cfg.getParameter("message");
if (AnnounceMessage.empty()) {
AnnounceMessage = "greeting_msg";
}
DefaultLanguage = cfg.getParameter("default_language");
if (DefaultLanguage.empty()) {
DefaultLanguage = "en";
}
try {
|
ffe99681 |
#ifdef VERSION2
|
18d97431 |
Connection.set_option(Connection.opt_reconnect, true);
|
ffe99681 |
#else
Connection.set_option(new mysqlpp::ReconnectOption(true));
#endif
|
a15202f0 |
Connection.connect(mysql_db.c_str(), mysql_server.c_str(),
mysql_user.c_str(), mysql_passwd.c_str());
if (!Connection) {
ERROR("Database connection failed: %s\n", Connection.error());
return -1;
}
}
|
18d97431 |
catch (const mysqlpp::BadOption& er) {
ERROR("MySQL++ set_option error: %s\n", er.what());
return -1;
}
|
a15202f0 |
catch (const mysqlpp::Exception& er) {
// Catch-all for any MySQL++ exceptions
ERROR("MySQL++ error: %s\n", er.what());
return -1;
}
string announce_file;
if (!get_announce_msg(AnnounceApplication, AnnounceMessage, "", "",
DefaultLanguage, &announce_file)) {
return -1;
}
if (announce_file.empty()) {
ERROR("default announce for " MOD_NAME " module does not exist.\n");
return -1;
}
#else
/* Get default audio from file system */
|
8d76c8bb |
AnnouncePath = cfg.getParameter("announce_path",ANNOUNCE_PATH);
if( !AnnouncePath.empty()
&& AnnouncePath[AnnouncePath.length()-1] != '/' )
AnnouncePath += "/";
|
b3e1c37c |
|
8d76c8bb |
AnnounceFile = cfg.getParameter("default_announce",ANNOUNCE_FILE);
|
b3e1c37c |
|
8d76c8bb |
string announce_file = AnnouncePath + AnnounceFile;
if(!file_exists(announce_file)){
ERROR("default file for " MOD_NAME " module does not exist ('%s').\n",
announce_file.c_str());
return -1;
}
|
b3e1c37c |
|
a15202f0 |
#endif
|
8d76c8bb |
return 0;
|
b3e1c37c |
}
|
1f5be2af |
void EarlyAnnounceDialog::onInvite(const AmSipRequest& req)
|
b3e1c37c |
{
|
8d76c8bb |
try {
|
b3e1c37c |
|
8d76c8bb |
string sdp_reply;
acceptAudio(req.body,req.hdrs,&sdp_reply);
|
b3e1c37c |
|
8d76c8bb |
if(dlg.reply(req,183,"Session Progress",
"application/sdp",sdp_reply) != 0){
|
b3e1c37c |
|
8d76c8bb |
throw AmSession::Exception(500,"could not reply");
}
|
2a0c6142 |
else {
invite_req = req;
|
8d76c8bb |
}
|
b3e1c37c |
|
8d76c8bb |
} catch(const AmSession::Exception& e) {
|
c75dd1ba |
|
8d76c8bb |
ERROR("%i %s\n",e.code,e.reason.c_str());
setStopped();
AmSipDialog::reply_error(req,e.code,e.reason);
}
|
b3e1c37c |
}
|
1f5be2af |
AmSession* EarlyAnnounceFactory::onInvite(const AmSipRequest& req)
|
b3e1c37c |
{
|
a15202f0 |
#ifdef USE_MYSQL
string iptel_app_param = getHeader(req.hdrs, PARAM_HDR);
string language = get_header_keyvalue(iptel_app_param,"Language");
string announce_file = "";
if (language.empty()) language = DefaultLanguage;
get_announce_msg(AnnounceApplication, AnnounceMessage, req.user,
req.domain, "", &announce_file);
if (!announce_file.empty()) goto end;
get_announce_msg(AnnounceApplication, AnnounceMessage, "", req.domain,
language, &announce_file);
if (!announce_file.empty()) goto end;
get_announce_msg(AnnounceApplication, AnnounceMessage, "", "", language,
&announce_file);
#else
|
8d76c8bb |
string announce_path = AnnouncePath;
string announce_file = announce_path + req.domain
|
7059248b |
+ "/" + req.user + ".wav";
|
b3e1c37c |
|
8d76c8bb |
DBG("trying '%s'\n",announce_file.c_str());
if(file_exists(announce_file))
goto end;
|
b3e1c37c |
|
8d76c8bb |
announce_file = announce_path + req.user + ".wav";
DBG("trying '%s'\n",announce_file.c_str());
if(file_exists(announce_file))
goto end;
|
b3e1c37c |
|
8d76c8bb |
announce_file = AnnouncePath + AnnounceFile;
|
a15202f0 |
#endif
|
8d76c8bb |
end:
return new EarlyAnnounceDialog(announce_file);
|
b3e1c37c |
}
|
1f5be2af |
EarlyAnnounceDialog::EarlyAnnounceDialog(const string& filename)
|
8d76c8bb |
: filename(filename)
|
b3e1c37c |
{
|
7dac246b |
set_sip_relay_only(false);
|
b3e1c37c |
}
|
1f5be2af |
EarlyAnnounceDialog::~EarlyAnnounceDialog()
|
b3e1c37c |
{
}
|
1f5be2af |
void EarlyAnnounceDialog::onSessionStart(const AmSipRequest& req)
|
b3e1c37c |
{
|
8d76c8bb |
// we can drop all received packets
// this disables DTMF detection as well
setReceiving(false);
|
ede1f718 |
|
8d76c8bb |
DBG("EarlyAnnounceDialog::onSessionStart\n");
if(wav_file.open(filename,AmAudioFile::Read))
throw string("EarlyAnnounceDialog::onSessionStart: Cannot open file\n");
|
b3e1c37c |
|
8d76c8bb |
setOutput(&wav_file);
|
b3e1c37c |
}
|
1f5be2af |
void EarlyAnnounceDialog::onBye(const AmSipRequest& req)
|
b3e1c37c |
{
|
8d76c8bb |
DBG("onBye: stopSession\n");
setStopped();
|
b3e1c37c |
}
|
1f5be2af |
void EarlyAnnounceDialog::onCancel()
|
b3e1c37c |
{
|
2a0c6142 |
dlg.reply(invite_req,487,"Call terminated");
|
8d76c8bb |
setStopped();
|
b3e1c37c |
}
|
1f5be2af |
void EarlyAnnounceDialog::process(AmEvent* event)
|
b3e1c37c |
{
|
8d76c8bb |
AmAudioEvent* audio_event = dynamic_cast<AmAudioEvent*>(event);
if(audio_event &&
|
94a0733f |
(audio_event->event_id == AmAudioEvent::cleared)) {
|
8d76c8bb |
DBG("AmAudioEvent::cleared\n");
|
7dac246b |
|
94a0733f |
bool continue_b2b = false;
if (EarlyAnnounceFactory::ContinueB2B ==
EarlyAnnounceFactory::Always) {
continue_b2b = true;
} else if (EarlyAnnounceFactory::ContinueB2B ==
EarlyAnnounceFactory::AppParam) {
|
2a0c6142 |
string iptel_app_param = getHeader(invite_req.hdrs, PARAM_HDR);
|
94a0733f |
if (iptel_app_param.length()) {
continue_b2b = get_header_keyvalue(iptel_app_param,"B2B")=="yes";
} else {
|
2a0c6142 |
continue_b2b = getHeader(invite_req.hdrs,"P-B2B")=="yes";
|
94a0733f |
}
}
DBG("determined: continue_b2b = %s\n", continue_b2b?"true":"false");
if (!continue_b2b) {
|
7dac246b |
unsigned int code_i = 404;
string reason = "Not Found";
|
2a0c6142 |
string iptel_app_param = getHeader(invite_req.hdrs, PARAM_HDR);
|
7dac246b |
if (iptel_app_param.length()) {
string code = get_header_keyvalue(iptel_app_param,"Final-Reply-Code");
if (code.length() && str2i(code, code_i)) {
ERROR("while parsing Final-Reply-Code parameter\n");
}
reason = get_header_keyvalue(iptel_app_param,"Final-Reply-Reason");
|
94a0733f |
if (!reason.length())
reason = "Not Found";
|
7dac246b |
} else {
|
2a0c6142 |
string code = getHeader(invite_req.hdrs,"P-Final-Reply-Code");
|
7dac246b |
if (code.length() && str2i(code, code_i)) {
ERROR("while parsing P-Final-Reply-Code\n");
}
|
2a0c6142 |
string h_reason = getHeader(invite_req.hdrs,"P-Final-Reply-Reason");
|
7dac246b |
if (h_reason.length()) {
INFO("Use of P-Final-Reply-Code/P-Final-Reply-Reason is deprecated. ");
INFO("Use '%s: Final-Reply-Code=<code>;"
"Final-Reply-Reason=<rs>' instead.\n",PARAM_HDR);
reason = h_reason;
}
|
73b06d8b |
}
|
7dac246b |
DBG("Replying with code %d %s\n", code_i, reason.c_str());
|
2a0c6142 |
dlg.reply(invite_req, code_i, reason);
|
fa35cb1c |
|
7dac246b |
setStopped();
} else {
set_sip_relay_only(true);
|
2a0c6142 |
recvd_req.insert(std::make_pair(invite_req.cseq,invite_req));
|
7dac246b |
|
2a0c6142 |
relayEvent(new B2BSipRequestEvent(invite_req,true));
|
7dac246b |
}
|
fa35cb1c |
|
8d76c8bb |
return;
|
b3e1c37c |
}
|
7dac246b |
AmB2BCallerSession::process(event);
|
b3e1c37c |
}
|