mirror of https://github.com/sipwise/sems.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
805 lines
23 KiB
805 lines
23 KiB
/*
|
|
* $Id$
|
|
*
|
|
* 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 "AnswerMachine.h"
|
|
#include "AmApi.h"
|
|
#include "AmSession.h"
|
|
#include "AmConfig.h"
|
|
#include "AmMail.h"
|
|
#include "AmUtils.h"
|
|
#include "AmPlugIn.h"
|
|
#include "AmPlaylist.h"
|
|
|
|
#include "../msg_storage/MsgStorageAPI.h"
|
|
#include "sems.h"
|
|
#include "log.h"
|
|
|
|
#ifdef USE_MYSQL
|
|
#include <mysql++/mysql++.h>
|
|
#include <stdio.h>
|
|
#include <sys/stat.h>
|
|
#include <time.h>
|
|
#define DEFAULT_TEMPLATE_TABLE "default_template"
|
|
#define DOMAIN_TEMPLATE_TABLE "domain_template"
|
|
#define DEFAULT_AUDIO_TABLE "default_audio"
|
|
#define DOMAIN_AUDIO_TABLE "domain_audio"
|
|
#define USER_AUDIO_TABLE "user_audio"
|
|
#define GREETING_MSG "greeting_msg"
|
|
#define BEEP_SOUND "beep_snd"
|
|
#define EMAIL_TMPL "email_tmpl"
|
|
#endif
|
|
|
|
#include <unistd.h>
|
|
#include <dirent.h>
|
|
|
|
#include <time.h>
|
|
|
|
#define MOD_NAME "voicemail"
|
|
#define DEFAULT_AUDIO_EXT "wav"
|
|
|
|
#define DEFAULT_MAIL_TMPL_PATH string("/usr/local/etc/sems")
|
|
#define DEFAULT_MAIL_TMPL string("default")
|
|
#define DEFAULT_MAIL_TMPL_EXT string("template")
|
|
|
|
#define RECORD_TIMER 99
|
|
|
|
EXPORT_SESSION_FACTORY(AnswerMachineFactory,MOD_NAME);
|
|
|
|
AnswerMachineFactory::AnswerMachineFactory(const string& _app_name)
|
|
: AmSessionFactory(_app_name)
|
|
{}
|
|
|
|
string AnswerMachineFactory::RecFileExt;
|
|
string AnswerMachineFactory::AnnouncePath;
|
|
string AnswerMachineFactory::DefaultAnnounce;
|
|
int AnswerMachineFactory::MaxRecordTime;
|
|
AmDynInvokeFactory* AnswerMachineFactory::UserTimer=0;
|
|
AmDynInvokeFactory* AnswerMachineFactory::MessageStorage=0;
|
|
bool AnswerMachineFactory::SaveEmptyMsg = true;
|
|
|
|
|
|
string AnswerMachineFactory::SmtpServerAddress = SMTP_ADDRESS_IP;
|
|
unsigned int AnswerMachineFactory::SmtpServerPort = SMTP_PORT;
|
|
|
|
#ifdef USE_MYSQL
|
|
mysqlpp::Connection AnswerMachineFactory::Connection(mysqlpp::use_exceptions);
|
|
|
|
int get_audio_file(string message, string domain, string user,
|
|
string language, string *audio_file)
|
|
{
|
|
string query_string;
|
|
|
|
if (!user.empty()) {
|
|
*audio_file = string("/tmp/") + domain + "_" + user + "_" +
|
|
MOD_NAME + "_" + message + ".wav";
|
|
query_string = "select audio from " + string(USER_AUDIO_TABLE) + " where application='" + MOD_NAME + "' and message='" + message + "' and domain='" + domain + "' and userid='" + user + "'";
|
|
} else {
|
|
if (language.empty()) {
|
|
if (domain.empty()) {
|
|
*audio_file = string("/tmp/") + MOD_NAME + "_" + message +
|
|
".wav";
|
|
query_string = "select audio from " + string(DEFAULT_AUDIO_TABLE) + " where application='" + MOD_NAME + "' and message='" + message + "' and language=''";
|
|
} else {
|
|
*audio_file = string("/tmp/") + domain + "_" + MOD_NAME +
|
|
"_" + message + ".wav";
|
|
query_string = "select audio from " + string(DOMAIN_AUDIO_TABLE) + " where application='" + MOD_NAME + "' and message='" + message + "' and domain='" + domain + "' and language=''";
|
|
}
|
|
} else {
|
|
if (domain.empty()) {
|
|
*audio_file = string("/tmp/") + MOD_NAME + "_" + message +
|
|
"_" + language + ".wav";
|
|
query_string = "select audio from " + string(DEFAULT_AUDIO_TABLE) + " where application='" + MOD_NAME + "' and message='" + message + "' and language='" + language + "'";
|
|
} else {
|
|
*audio_file = string("/tmp/") + domain + "_" + MOD_NAME + "_" +
|
|
message + "_" + language + ".wav";
|
|
query_string = "select audio from " + string(DOMAIN_AUDIO_TABLE) + " where application='" + MOD_NAME + "' and message='" + message + "' and domain='" + domain + "' and language='" + language + "'";
|
|
}
|
|
}
|
|
}
|
|
|
|
try {
|
|
|
|
mysqlpp::Query query = AnswerMachineFactory::Connection.query();
|
|
|
|
DBG("Query string <%s>\n", query_string.c_str());
|
|
|
|
query << query_string;
|
|
mysqlpp::Result res = query.store();
|
|
|
|
mysqlpp::Row row;
|
|
|
|
if (res) {
|
|
if ((res.num_rows() > 0) && (row = res.at(0))) {
|
|
FILE *file;
|
|
unsigned long length = row.raw_string(0).size();
|
|
file = fopen((*audio_file).c_str(), "wb");
|
|
fwrite(row.at(0).data(), 1, length, file);
|
|
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;
|
|
}
|
|
}
|
|
|
|
int AnswerMachineFactory::loadEmailTemplatesFromMySQL()
|
|
{
|
|
|
|
try {
|
|
|
|
mysqlpp::Query query = AnswerMachineFactory::Connection.query();
|
|
|
|
string query_string, table;
|
|
query_string = "select replace(template, '\r', '') as template, language from " + string(DEFAULT_TEMPLATE_TABLE) + " where application='" + MOD_NAME + "' and message='" + EMAIL_TMPL + "'";
|
|
|
|
DBG("Query string <%s>\n", query_string.c_str());
|
|
|
|
query << query_string;
|
|
mysqlpp::Result res = query.store();
|
|
|
|
mysqlpp::Row::size_type i;
|
|
mysqlpp::Row::size_type row_count = res.num_rows();
|
|
mysqlpp::Row row;
|
|
|
|
for (i = 0; i < row_count; i++) {
|
|
row = res.at(i);
|
|
FILE *file;
|
|
unsigned long length = row["template"].size();
|
|
string tmp_file, tmpl_name;
|
|
row = res.at(i);
|
|
if (string(row["language"]) == "") {
|
|
tmp_file = "/tmp/voicemail_email.template";
|
|
tmpl_name = DEFAULT_MAIL_TMPL;
|
|
} else {
|
|
tmp_file = string("/tmp/voicemail_email_") +
|
|
string(row["language"]) + ".template";
|
|
tmpl_name = DEFAULT_MAIL_TMPL + "_" +
|
|
string(row["language"]);
|
|
}
|
|
file = fopen(tmp_file.c_str(), "wb");
|
|
fwrite(row["template"], 1, length, file);
|
|
fclose(file);
|
|
DBG("loading %s as %s ...\n", tmp_file.c_str(), tmpl_name.c_str());
|
|
EmailTemplate tmp_tmpl;
|
|
if (tmp_tmpl.load(tmp_file)) {
|
|
ERROR("Voicemail: could not load default"
|
|
" email template: '%s'\n", tmp_file.c_str());
|
|
return -1;
|
|
} else {
|
|
email_tmpl[tmpl_name] = tmp_tmpl;
|
|
}
|
|
}
|
|
if (email_tmpl.count(DEFAULT_MAIL_TMPL) == 0) {
|
|
ERROR("Voicemail: default email template does not exist\n");
|
|
return -1;
|
|
}
|
|
|
|
query_string = "select domain, replace(template, '\r', '') as template, language from " + string(DOMAIN_TEMPLATE_TABLE) + " where application='" + MOD_NAME +"' and message='" + EMAIL_TMPL + "'";
|
|
|
|
DBG("Query string <%s>\n", query_string.c_str());
|
|
|
|
query << query_string;
|
|
res = query.store();
|
|
|
|
row_count = res.num_rows();
|
|
|
|
for (i = 0; i < row_count; i++) {
|
|
row = res.at(i);
|
|
FILE *file;
|
|
unsigned long length = row["template"].size();
|
|
string tmp_file, tmpl_name;
|
|
row = res.at(i);
|
|
if (string(row["language"]) == "") {
|
|
tmp_file = "/tmp/" + string(row["domain"]) +
|
|
"_voicemail_email.template";
|
|
tmpl_name = string(row["domain"]);
|
|
} else {
|
|
tmp_file = string("/tmp/") + string(row["domain"]) +
|
|
"_voicemail_email_" + string(row["language"]) +
|
|
".template";
|
|
tmpl_name = string(row["domain"]) + "_" +
|
|
string(row["language"]);
|
|
}
|
|
file = fopen(tmp_file.c_str(), "wb");
|
|
fwrite(row["template"], 1, length, file);
|
|
fclose(file);
|
|
DBG("loading %s as %s ...\n",tmp_file.c_str(), tmpl_name.c_str());
|
|
EmailTemplate tmp_tmpl;
|
|
if (tmp_tmpl.load(tmp_file) < 0) {
|
|
ERROR("Voicemail: could not load default"
|
|
" email template: '%s'\n", tmp_file.c_str());
|
|
return -1;
|
|
} else {
|
|
email_tmpl[tmpl_name] = tmp_tmpl;
|
|
}
|
|
}
|
|
}
|
|
|
|
catch (const mysqlpp::Exception& er) {
|
|
// Catch-all for any MySQL++ exceptions
|
|
ERROR("MySQL++ error: %s\n", er.what());
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
|
|
|
|
int AnswerMachineFactory::loadEmailTemplates(const string& path)
|
|
{
|
|
string email_tmpl_file = add2path(path, 1,
|
|
(DEFAULT_MAIL_TMPL + "."
|
|
+ DEFAULT_MAIL_TMPL_EXT).c_str());
|
|
|
|
EmailTemplate& tmpl = email_tmpl[DEFAULT_MAIL_TMPL];
|
|
if(tmpl.load(email_tmpl_file)){
|
|
ERROR("Voicemail: could not load default"
|
|
" email template: '%s'\n",
|
|
email_tmpl_file.c_str());
|
|
return -1;
|
|
}
|
|
|
|
int err=0;
|
|
struct dirent* entry=0;
|
|
DIR* dir = opendir(path.c_str());
|
|
|
|
if(!dir){
|
|
ERROR("Voicemail: email template loader (%s): %s\n",
|
|
path.c_str(),strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
string file_ext = string(".") + DEFAULT_MAIL_TMPL_EXT;
|
|
while( ((entry = readdir(dir)) != NULL) && (err == 0) ){
|
|
|
|
string tmpl_file = add2path(path,1,entry->d_name);
|
|
string tmpl_name = entry->d_name;
|
|
|
|
if( (tmpl_name.length() <= file_ext.length())
|
|
|| tmpl_name.substr( tmpl_name.length()
|
|
- file_ext.length(),
|
|
file_ext.length() )
|
|
!= file_ext ){
|
|
continue;
|
|
}
|
|
tmpl_name = tmpl_name.substr( 0, tmpl_name.length()
|
|
- file_ext.length() );
|
|
|
|
DBG("loading %s ...\n",tmpl_file.c_str());
|
|
EmailTemplate tmp_tmpl;
|
|
if( (err = tmp_tmpl.load(tmpl_file)) < 0 )
|
|
ERROR("Voicemail: while loading template '%s'\n",tmpl_file.c_str());
|
|
else
|
|
email_tmpl[tmpl_name] = tmp_tmpl;
|
|
}
|
|
|
|
closedir(dir);
|
|
return err;
|
|
}
|
|
|
|
#endif
|
|
|
|
int AnswerMachineFactory::onLoad()
|
|
{
|
|
AmConfigReader cfg;
|
|
if(cfg.loadFile(add2path(AmConfig::ModConfigPath,1, MOD_NAME ".conf")))
|
|
return -1;
|
|
|
|
// get application specific global parameters
|
|
configureModule(cfg);
|
|
|
|
// smtp_server
|
|
SmtpServerAddress = cfg.getParameter("smtp_server",SmtpServerAddress);
|
|
|
|
// smtp_port
|
|
if(cfg.hasParameter("smtp_port")){
|
|
if(sscanf(cfg.getParameter("smtp_port").c_str(),
|
|
"%u",&SmtpServerPort) != 1) {
|
|
ERROR("invalid smtp_port specified\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
DBG("SMTP server set to %s:%u\n",
|
|
SmtpServerAddress.c_str(), SmtpServerPort);
|
|
|
|
#ifdef USE_MYSQL
|
|
|
|
/* Get email templates 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()) {
|
|
ERROR("voicemail.conf paramater 'mysql_user' is missing.\n");
|
|
return -1;
|
|
}
|
|
|
|
mysql_passwd = cfg.getParameter("mysql_passwd");
|
|
if (mysql_passwd.empty()) {
|
|
ERROR("voicemail.conf paramater 'mysql_passwd' is missing.\n");
|
|
return -1;
|
|
}
|
|
|
|
mysql_db = cfg.getParameter("mysql_db");
|
|
if (mysql_db.empty()) {
|
|
mysql_db = "sems";
|
|
}
|
|
|
|
try {
|
|
|
|
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;
|
|
}
|
|
Connection.set_option(mysqlpp::Connection::opt_reconnect, true);
|
|
}
|
|
|
|
catch (const mysqlpp::Exception& er) {
|
|
// Catch-all for any MySQL++ exceptions
|
|
ERROR("MySQL++ error: %s\n", er.what());
|
|
return -1;
|
|
}
|
|
|
|
if(loadEmailTemplatesFromMySQL()){
|
|
ERROR("while loading email templates from MySQL\n");
|
|
return -1;
|
|
}
|
|
|
|
#else
|
|
|
|
/* Get email templates from file system */
|
|
|
|
if(loadEmailTemplates(cfg.getParameter("email_template_path",DEFAULT_MAIL_TMPL_PATH))){
|
|
ERROR("while loading email templates\n");
|
|
return -1;
|
|
}
|
|
|
|
AnnouncePath = cfg.getParameter("announce_path");
|
|
DefaultAnnounce = cfg.getParameter("default_announce");
|
|
|
|
#endif
|
|
|
|
MaxRecordTime = cfg.getParameterInt("max_record_time",DEFAULT_RECORD_TIME);
|
|
RecFileExt = cfg.getParameter("rec_file_ext",DEFAULT_AUDIO_EXT);
|
|
|
|
UserTimer = AmPlugIn::instance()->getFactory4Di("user_timer");
|
|
if(!UserTimer){
|
|
|
|
ERROR("could not load user_timer from session_timer plug-in\n");
|
|
return -1;
|
|
}
|
|
|
|
MessageStorage = NULL;
|
|
MessageStorage = AmPlugIn::instance()->getFactory4Di("msg_storage");
|
|
if(NULL == MessageStorage){
|
|
INFO("could not load msg_storage. Voice Box mode will not be available.\n");
|
|
}
|
|
|
|
DBG("Starting SMTP daemon\n");
|
|
AmMailDeamon::instance()->start();
|
|
|
|
string s_save_empty_msg = cfg.getParameter("box_save_empty_msg");
|
|
if (!s_save_empty_msg.empty()) {
|
|
SaveEmptyMsg = !(s_save_empty_msg == "no");
|
|
}
|
|
DBG("Voicebox will%s save empty messages.\n",
|
|
SaveEmptyMsg?"":" not");
|
|
|
|
return 0;
|
|
}
|
|
|
|
AmSession* AnswerMachineFactory::onInvite(const AmSipRequest& req)
|
|
{
|
|
string language;
|
|
string email;
|
|
string domain;
|
|
string user;
|
|
string sender;
|
|
|
|
int vm_mode = MODE_VOICEMAIL;
|
|
|
|
string iptel_app_param = getHeader(req.hdrs, PARAM_HDR);
|
|
|
|
if (!iptel_app_param.length()) {
|
|
AmSession::Exception(500, "voicemail: parameters not found");
|
|
}
|
|
|
|
language = get_header_keyvalue(iptel_app_param,"Language");
|
|
email = get_header_keyvalue(iptel_app_param,"Email-Address");
|
|
string mode = get_header_keyvalue(iptel_app_param,"Mode");
|
|
if (!mode.empty()) {
|
|
if (mode == "box")
|
|
vm_mode = MODE_BOX;
|
|
else if (mode == "both")
|
|
vm_mode = MODE_BOTH;
|
|
}
|
|
|
|
user = get_header_keyvalue(iptel_app_param,"User");
|
|
sender = get_header_keyvalue(iptel_app_param,"Sender");
|
|
domain = get_header_keyvalue(iptel_app_param,"Domain");
|
|
|
|
// checks
|
|
if (user.empty())
|
|
throw AmSession::Exception(500, "voicemail: user missing");
|
|
|
|
if (sender.empty())
|
|
throw AmSession::Exception(500, "voicemail: sender missing");
|
|
|
|
if (((vm_mode == MODE_BOX) || (vm_mode == MODE_BOTH))
|
|
&& (NULL == MessageStorage)) {
|
|
throw AmSession::Exception(500, "voicemail: no message storage available");
|
|
}
|
|
|
|
|
|
DBG("voicemail invocation parameters: \n");
|
|
DBG(" Mode: <%s> \n", mode.c_str());
|
|
DBG(" User: <%s> \n", user.c_str());
|
|
DBG(" Sender: <%s> \n", sender.c_str());
|
|
DBG(" Domain: <%s> \n", domain.c_str());
|
|
DBG(" Language: <%s> \n", language.c_str());
|
|
|
|
#ifdef USE_MYSQL
|
|
|
|
string announce_file;
|
|
|
|
if (get_audio_file(GREETING_MSG, domain, req.user, "",
|
|
&announce_file) && !announce_file.empty())
|
|
goto announce_found;
|
|
|
|
if (!language.empty()) {
|
|
if (get_audio_file(GREETING_MSG, domain, "", language,
|
|
&announce_file) && !announce_file.empty())
|
|
goto announce_found;
|
|
} else {
|
|
if (get_audio_file(GREETING_MSG, domain, "", "",
|
|
&announce_file) && !announce_file.empty())
|
|
goto announce_found;
|
|
}
|
|
|
|
if (!language.empty())
|
|
if (get_audio_file(GREETING_MSG, "", "", language,
|
|
&announce_file) && !announce_file.empty())
|
|
goto announce_found;
|
|
|
|
get_audio_file(GREETING_MSG, "", "", "", &announce_file);
|
|
|
|
#else
|
|
|
|
string announce_file = add2path(AnnouncePath,2, domain.c_str(), (user + ".wav").c_str());
|
|
if (file_exists(announce_file)) goto announce_found;
|
|
|
|
if (!language.empty()) {
|
|
announce_file = add2path(AnnouncePath,3, domain.c_str(), language.c_str(), DefaultAnnounce.c_str());
|
|
if (file_exists(announce_file)) goto announce_found;
|
|
}
|
|
|
|
announce_file = add2path(AnnouncePath,2, domain.c_str(), DefaultAnnounce.c_str());
|
|
if (file_exists(announce_file)) goto announce_found;
|
|
|
|
if (!language.empty()) {
|
|
announce_file = add2path(AnnouncePath,2, language.c_str(), DefaultAnnounce.c_str());
|
|
if (file_exists(announce_file)) goto announce_found;
|
|
}
|
|
|
|
announce_file = add2path(AnnouncePath,1, DefaultAnnounce.c_str());
|
|
if (!file_exists(announce_file))
|
|
announce_file = "";
|
|
|
|
#endif
|
|
|
|
announce_found:
|
|
if(announce_file.empty())
|
|
throw AmSession::Exception(500,"voicemail: no greeting file found");
|
|
|
|
// VBOX mode does not need email template
|
|
if (vm_mode == MODE_BOX)
|
|
return new AnswerMachineDialog(user, sender, domain,
|
|
email, announce_file,
|
|
vm_mode, NULL);
|
|
|
|
if(email.empty())
|
|
throw AmSession::Exception(404,"missing email address");
|
|
|
|
map<string,EmailTemplate>::iterator tmpl_it;
|
|
if (!language.empty()) {
|
|
tmpl_it = email_tmpl.find(domain + "_" + language);
|
|
if(tmpl_it == email_tmpl.end()) {
|
|
tmpl_it = email_tmpl.find(domain);
|
|
if(tmpl_it == email_tmpl.end()) {
|
|
tmpl_it = email_tmpl.find(DEFAULT_MAIL_TMPL + "_"
|
|
+ language);
|
|
if(tmpl_it == email_tmpl.end())
|
|
tmpl_it = email_tmpl.find(DEFAULT_MAIL_TMPL);
|
|
}
|
|
}
|
|
} else {
|
|
tmpl_it = email_tmpl.find(domain);
|
|
if(tmpl_it == email_tmpl.end())
|
|
tmpl_it = email_tmpl.find(DEFAULT_MAIL_TMPL);
|
|
}
|
|
|
|
if(tmpl_it == email_tmpl.end()){
|
|
ERROR("Voicemail: unable to find an email template.\n");
|
|
return 0;
|
|
}
|
|
return new AnswerMachineDialog(user, sender, domain,
|
|
email, announce_file,
|
|
vm_mode, &tmpl_it->second);
|
|
}
|
|
|
|
|
|
AnswerMachineDialog::AnswerMachineDialog(const string& user,
|
|
const string& sender,
|
|
const string& domain,
|
|
const string& email,
|
|
const string& announce_file,
|
|
int vm_mode,
|
|
const EmailTemplate* tmpl)
|
|
: announce_file(announce_file),
|
|
tmpl(tmpl), playlist(this),
|
|
status(0), vm_mode(vm_mode)
|
|
{
|
|
email_dict["user"] = user;
|
|
email_dict["sender"] = sender;
|
|
email_dict["domain"] = domain;
|
|
email_dict["email"] = email;
|
|
|
|
user_timer = AnswerMachineFactory::UserTimer->getInstance();
|
|
if(!user_timer){
|
|
ERROR("could not get a user timer reference\n");
|
|
throw AmSession::Exception(500,"could not get a user timer reference");
|
|
}
|
|
|
|
if (vm_mode == MODE_BOTH || vm_mode == MODE_BOX) {
|
|
msg_storage = AnswerMachineFactory::MessageStorage->getInstance();
|
|
if(!msg_storage){
|
|
ERROR("could not get a message storage reference\n");
|
|
throw AmSession::Exception(500,"could not get a message storage reference");
|
|
}
|
|
}
|
|
}
|
|
|
|
AnswerMachineDialog::~AnswerMachineDialog()
|
|
{
|
|
playlist.close(false);
|
|
}
|
|
|
|
void AnswerMachineDialog::process(AmEvent* event)
|
|
{
|
|
AmAudioEvent* ae = dynamic_cast<AmAudioEvent*>(event);
|
|
if(ae){
|
|
|
|
switch(ae->event_id){
|
|
|
|
case AmAudioEvent::noAudio:
|
|
|
|
switch(status){
|
|
|
|
case 0:
|
|
playlist.addToPlaylist(new AmPlaylistItem(NULL,&a_msg));
|
|
|
|
{AmArg di_args,ret;
|
|
di_args.push(RECORD_TIMER);
|
|
di_args.push(AnswerMachineFactory::MaxRecordTime);
|
|
di_args.push(getLocalTag().c_str());
|
|
|
|
user_timer->invoke("setTimer",di_args,ret);}
|
|
status = 1;
|
|
break;
|
|
|
|
case 1:
|
|
a_beep.rewind();
|
|
playlist.addToPlaylist(new AmPlaylistItem(&a_beep,NULL));
|
|
status = 2;
|
|
break;
|
|
|
|
case 2:
|
|
dlg.bye();
|
|
saveMessage();
|
|
setStopped();
|
|
break;
|
|
|
|
}
|
|
break;
|
|
|
|
case AmAudioEvent::cleared:
|
|
DBG("AmAudioEvent::cleared\n");
|
|
break;
|
|
|
|
default:
|
|
DBG("Unknown event id %i\n",ae->event_id);
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
AmPluginEvent* plugin_event = dynamic_cast<AmPluginEvent*>(event);
|
|
if(plugin_event && plugin_event->name == "timer_timeout" &&
|
|
plugin_event->data.get(0).asInt() == RECORD_TIMER) {
|
|
|
|
// clear list
|
|
playlist.close();
|
|
}
|
|
else
|
|
AmSession::process(event);
|
|
}
|
|
|
|
void AnswerMachineDialog::onSessionStart(const AmSipRequest& req)
|
|
{
|
|
// disable DTMF detection - don't use DTMF here
|
|
setDtmfDetectionEnabled(false);
|
|
|
|
#ifdef USE_MYSQL
|
|
string beep_file;
|
|
if (!get_audio_file(BEEP_SOUND, "", "", "", &beep_file) ||
|
|
beep_file.empty())
|
|
throw string("AnswerMachine: could not find beep file\n");
|
|
if (a_greeting.open(announce_file.c_str(),AmAudioFile::Read) ||
|
|
a_beep.open(beep_file,AmAudioFile::Read))
|
|
throw string("AnswerMachine: could not open greeting or beep file\n");
|
|
#else
|
|
if (a_greeting.open(announce_file.c_str(),AmAudioFile::Read) ||
|
|
a_beep.open(add2path(AnswerMachineFactory::AnnouncePath,1, "beep.wav"),AmAudioFile::Read))
|
|
throw string("AnswerMachine: could not open annoucement files\n");
|
|
#endif
|
|
|
|
msg_filename = "/tmp/" + getLocalTag() + "."
|
|
+ AnswerMachineFactory::RecFileExt;
|
|
|
|
if(a_msg.open(msg_filename,AmAudioFile::Write,true))
|
|
throw string("AnswerMachine: couldn't open ") +
|
|
msg_filename + string(" for writing");
|
|
|
|
//a_msg.setRecordTime(AnswerMachineFactory::MaxRecordTime*1000);
|
|
|
|
playlist.addToPlaylist(new AmPlaylistItem(&a_greeting,NULL));
|
|
playlist.addToPlaylist(new AmPlaylistItem(&a_beep,NULL));
|
|
//playlist.addToPlaylist(new AmPlaylistItem(NULL,&a_msg));
|
|
|
|
setInOut(&playlist,&playlist);
|
|
|
|
char now[15];
|
|
sprintf(now, "%d", (int) time(NULL));
|
|
email_dict["ts"] = now;
|
|
|
|
}
|
|
|
|
void AnswerMachineDialog::onBye(const AmSipRequest& req)
|
|
{
|
|
setInOut(NULL, NULL);
|
|
saveMessage();
|
|
setStopped();
|
|
}
|
|
|
|
void AnswerMachineDialog::saveMessage()
|
|
{
|
|
char buf[1024];
|
|
unsigned int rec_size = a_msg.getDataSize();
|
|
DBG("recorded data size: %i\n",rec_size);
|
|
|
|
if(!rec_size){
|
|
unlink(msg_filename.c_str());
|
|
|
|
// record in box empty messages as well
|
|
if (AnswerMachineFactory::SaveEmptyMsg &&
|
|
((vm_mode == MODE_BOX) ||
|
|
(vm_mode == MODE_BOTH))) {
|
|
saveBox(NULL);
|
|
}
|
|
} else {
|
|
try {
|
|
// avoid tmp file to be closed
|
|
// ~AmMail will do that...
|
|
a_msg.setCloseOnDestroy(false);
|
|
a_msg.on_close();
|
|
|
|
// copy to tmpfile for box msg
|
|
if ((vm_mode == MODE_BOTH) ||
|
|
(vm_mode == MODE_BOX)) {
|
|
DBG("will save to box...\n");
|
|
FILE* m_fp = a_msg.getfp();
|
|
|
|
if (vm_mode == MODE_BOTH) {
|
|
// copy file to new tmpfile
|
|
m_fp = tmpfile();
|
|
if(!m_fp){
|
|
ERROR("could not create temporary file: %s\n",
|
|
strerror(errno));
|
|
} else {
|
|
FILE* fp = a_msg.getfp();
|
|
rewind(fp);
|
|
size_t nread;
|
|
while (!feof(fp)) {
|
|
nread = fread(buf, 1, 1024, fp);
|
|
if (fwrite(buf, 1, nread, m_fp) != nread)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
saveBox(m_fp);
|
|
}
|
|
|
|
if ((vm_mode == MODE_BOTH) ||
|
|
(vm_mode == MODE_VOICEMAIL)) {
|
|
// send mail
|
|
AmMail* mail = new AmMail(tmpl->getEmail(email_dict));
|
|
mail->attachements.push_back(Attachement(a_msg.getfp(),
|
|
"message."
|
|
+ AnswerMachineFactory::RecFileExt,
|
|
a_msg.getMimeType()));
|
|
AmMailDeamon::instance()->sendQueued(mail);
|
|
}
|
|
}
|
|
catch(const string& err){
|
|
ERROR("while creating email: %s\n",err.c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void AnswerMachineDialog::saveBox(FILE* fp) {
|
|
string msg_name = email_dict["ts"] + MSG_SEPARATOR +
|
|
email_dict["sender"] + ".wav";
|
|
DBG("message name is '%s'\n", msg_name.c_str());
|
|
|
|
AmArg di_args,ret;
|
|
di_args.push(email_dict["domain"].c_str()); // domain
|
|
di_args.push(email_dict["user"].c_str()); // user
|
|
di_args.push(msg_name.c_str()); // message name
|
|
AmArg df;
|
|
MessageDataFile df_arg(fp);
|
|
df.setBorrowedPointer(&df_arg);
|
|
di_args.push(df);
|
|
msg_storage->invoke("msg_new",di_args,ret);
|
|
// TODO: evaluate ret return value
|
|
fclose(fp);
|
|
}
|
|
|