2015-09-28 23:25:12 +02:00
|
|
|
#include "PjsuaCommunicator.hpp"
|
|
|
|
#include "MumbleCommunicator.hpp"
|
2015-11-09 00:51:51 +01:00
|
|
|
#include "IncomingConnectionValidator.hpp"
|
2015-11-30 23:24:41 +01:00
|
|
|
#include "MumbleChannelJoiner.hpp"
|
2015-10-17 22:27:37 +02:00
|
|
|
#include "Configuration.hpp"
|
2015-07-13 18:14:35 +02:00
|
|
|
|
2015-11-05 01:15:20 +01:00
|
|
|
#include <log4cpp/FileAppender.hh>
|
|
|
|
#include <log4cpp/OstreamAppender.hh>
|
2015-11-09 00:51:51 +01:00
|
|
|
#include <log4cpp/PatternLayout.hh>
|
2015-11-05 01:15:20 +01:00
|
|
|
|
2015-12-14 22:58:31 +01:00
|
|
|
#include <execinfo.h>
|
2020-03-29 20:23:56 +02:00
|
|
|
#include <memory>
|
2015-12-14 22:58:31 +01:00
|
|
|
|
2017-05-24 22:38:45 +02:00
|
|
|
#include "main.hpp"
|
|
|
|
|
2020-03-29 20:23:56 +02:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
std::weak_ptr<boost::asio::io_service> g_ioService;
|
|
|
|
|
2015-12-14 22:58:31 +01:00
|
|
|
/*
|
|
|
|
* Code from http://stackoverflow.com/a/77336/5419223
|
|
|
|
*/
|
2020-03-29 20:23:56 +02:00
|
|
|
void sigsegv_handler(int sig) {
|
2015-12-14 22:58:31 +01:00
|
|
|
constexpr int STACK_DEPTH = 10;
|
|
|
|
void *array[STACK_DEPTH];
|
|
|
|
|
|
|
|
size_t size = backtrace(array, STACK_DEPTH);
|
|
|
|
|
|
|
|
fprintf(stderr, "ERROR: signal %d:\n", sig);
|
|
|
|
backtrace_symbols_fd(array, size, STDERR_FILENO);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2020-03-29 20:23:56 +02:00
|
|
|
void sigint_handler(int sig)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Caught SIGINT, trying to stop\n");
|
|
|
|
if (auto io = g_ioService.lock()) {
|
|
|
|
io->stop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetupSignalHandlers()
|
|
|
|
{
|
|
|
|
struct sigaction sigIntHandler;
|
|
|
|
|
|
|
|
sigIntHandler.sa_handler = sigsegv_handler;
|
|
|
|
sigemptyset(&sigIntHandler.sa_mask);
|
|
|
|
sigIntHandler.sa_flags = 0;
|
|
|
|
|
|
|
|
sigaction(SIGSEGV, &sigIntHandler, NULL);
|
|
|
|
|
|
|
|
memset(&sigIntHandler, 0, sizeof(sigIntHandler));
|
|
|
|
sigIntHandler.sa_handler = sigint_handler;
|
|
|
|
sigemptyset(&sigIntHandler.sa_mask);
|
|
|
|
sigIntHandler.sa_flags = 0;
|
|
|
|
|
|
|
|
sigaction(SIGINT, &sigIntHandler, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
2015-07-20 21:09:22 +02:00
|
|
|
int main(int argc, char *argv[]) {
|
2020-03-29 20:23:56 +02:00
|
|
|
SetupSignalHandlers();
|
2017-05-24 22:38:45 +02:00
|
|
|
int max_calls;
|
2015-07-20 21:09:22 +02:00
|
|
|
|
2016-01-20 21:47:44 +01:00
|
|
|
log4cpp::OstreamAppender appender("console", &std::cout);
|
2015-11-09 00:51:51 +01:00
|
|
|
log4cpp::PatternLayout layout;
|
|
|
|
layout.setConversionPattern("%d [%p] %c: %m%n");
|
2016-01-20 21:47:44 +01:00
|
|
|
appender.setLayout(&layout);
|
2015-09-29 02:26:45 +02:00
|
|
|
log4cpp::Category &logger = log4cpp::Category::getRoot();
|
2017-05-24 22:38:45 +02:00
|
|
|
logger.setPriority(log4cpp::Priority::DEBUG);
|
|
|
|
//logger.setPriority(log4cpp::Priority::NOTICE);
|
2016-01-20 21:47:44 +01:00
|
|
|
logger.addAppender(appender);
|
2015-07-20 21:09:22 +02:00
|
|
|
|
2015-10-17 22:27:37 +02:00
|
|
|
if (argc == 1) {
|
|
|
|
logger.crit("No configuration file provided. Use %s {config file}", argv[0]);
|
2016-01-20 21:47:44 +01:00
|
|
|
std::exit(1);
|
2015-10-17 22:27:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
config::Configuration conf(argv[1]);
|
2015-10-16 22:41:37 +02:00
|
|
|
|
2016-04-18 01:30:10 +02:00
|
|
|
logger.setPriority(log4cpp::Priority::getPriorityValue(conf.getString("general.logLevel")));
|
|
|
|
|
2015-11-09 00:51:51 +01:00
|
|
|
sip::IncomingConnectionValidator connectionValidator(conf.getString("sip.validUriExpression"));
|
|
|
|
|
2020-03-29 20:23:56 +02:00
|
|
|
auto ioService = std::make_shared<boost::asio::io_service>();
|
|
|
|
g_ioService = ioService;
|
2015-10-30 13:43:06 +01:00
|
|
|
|
2017-05-24 22:38:45 +02:00
|
|
|
try {
|
|
|
|
max_calls = conf.getInt("sip.max_calls");
|
|
|
|
} catch (...) {
|
|
|
|
max_calls = 1;
|
|
|
|
}
|
2015-11-30 23:24:41 +01:00
|
|
|
|
2017-05-24 22:38:45 +02:00
|
|
|
sip::PjsuaCommunicator pjsuaCommunicator(connectionValidator, conf.getInt("sip.frameLength"), max_calls);
|
2015-11-30 23:24:41 +01:00
|
|
|
|
2017-05-27 22:12:26 +02:00
|
|
|
try {
|
|
|
|
pjsuaCommunicator.pins = conf.getChildren("pins");
|
|
|
|
} catch (...) {
|
|
|
|
}
|
|
|
|
|
2016-04-18 01:22:36 +02:00
|
|
|
mumble::MumbleCommunicatorConfig mumbleConf;
|
|
|
|
mumbleConf.host = conf.getString("mumble.host");
|
|
|
|
mumbleConf.port = conf.getInt("mumble.port");
|
|
|
|
mumbleConf.user = conf.getString("mumble.user");
|
|
|
|
mumbleConf.password = conf.getString("mumble.password");
|
|
|
|
mumbleConf.opusEncoderBitrate = conf.getInt("mumble.opusEncoderBitrate");
|
2017-05-20 18:17:08 +02:00
|
|
|
/* default to 'false' if not found */
|
|
|
|
try {
|
|
|
|
mumbleConf.autodeaf = conf.getBool("mumble.autodeaf");
|
|
|
|
} catch (...) {
|
|
|
|
mumbleConf.autodeaf = false;
|
|
|
|
}
|
2016-04-18 01:22:36 +02:00
|
|
|
|
2017-05-24 22:38:45 +02:00
|
|
|
try {
|
|
|
|
mumbleConf.comment = conf.getString("app.comment");
|
|
|
|
} catch (...) {
|
|
|
|
mumbleConf.comment = "";
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:16:11 +02:00
|
|
|
try { pjsuaCommunicator.file_welcome = conf.getString("files.welcome");
|
2017-05-22 12:15:07 +02:00
|
|
|
} catch (...) {
|
|
|
|
pjsuaCommunicator.file_welcome = "welcome.wav";
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:16:11 +02:00
|
|
|
try { pjsuaCommunicator.file_prompt_pin = conf.getString("files.prompt_pin");
|
2017-05-22 12:15:07 +02:00
|
|
|
} catch (...) {
|
|
|
|
pjsuaCommunicator.file_prompt_pin = "prompt-pin.wav";
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:16:11 +02:00
|
|
|
try { pjsuaCommunicator.file_entering_channel = conf.getString("files.entering_channel");
|
2017-05-22 12:15:07 +02:00
|
|
|
} catch (...) {
|
|
|
|
pjsuaCommunicator.file_entering_channel = "entering-channel.wav";
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:16:11 +02:00
|
|
|
try { pjsuaCommunicator.file_announce_new_caller = conf.getString("files.announce_new_caller");
|
2017-05-22 12:15:07 +02:00
|
|
|
} catch (...) {
|
|
|
|
pjsuaCommunicator.file_announce_new_caller = "announce-new-caller.wav";
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:16:11 +02:00
|
|
|
try { pjsuaCommunicator.file_invalid_pin = conf.getString("files.invalid_pin");
|
2017-05-22 12:15:07 +02:00
|
|
|
} catch (...) {
|
|
|
|
pjsuaCommunicator.file_invalid_pin = "invalid-pin.wav";
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:16:11 +02:00
|
|
|
try { pjsuaCommunicator.file_goodbye = conf.getString("files.goodbye");
|
2017-05-22 12:15:07 +02:00
|
|
|
} catch (...) {
|
|
|
|
pjsuaCommunicator.file_goodbye = "goodbye.wav";
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:16:11 +02:00
|
|
|
try { pjsuaCommunicator.file_mute_on = conf.getString("files.mute_on");
|
2017-05-22 12:15:07 +02:00
|
|
|
} catch (...) {
|
|
|
|
pjsuaCommunicator.file_mute_on = "mute-on.wav";
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:16:11 +02:00
|
|
|
try { pjsuaCommunicator.file_mute_off = conf.getString("files.mute_off");
|
2017-05-22 12:15:07 +02:00
|
|
|
} catch (...) {
|
|
|
|
pjsuaCommunicator.file_mute_off = "mute-off.wav";
|
|
|
|
}
|
|
|
|
|
2017-05-27 17:16:11 +02:00
|
|
|
try { pjsuaCommunicator.file_menu = conf.getString("files.menu");
|
2017-05-22 12:15:07 +02:00
|
|
|
} catch (...) {
|
|
|
|
pjsuaCommunicator.file_menu = "menu.wav";
|
2017-05-21 16:03:19 +02:00
|
|
|
}
|
|
|
|
|
2017-05-24 22:38:45 +02:00
|
|
|
std::string defaultChan = conf.getString("mumble.channelNameExpression");
|
|
|
|
|
|
|
|
mumble::MumbleChannelJoiner mumbleChannelJoiner(defaultChan);
|
2017-05-27 22:12:26 +02:00
|
|
|
mumble::MumbleChannelJoiner mumbleOtherChannelJoiner(defaultChan);
|
2017-05-24 22:38:45 +02:00
|
|
|
|
|
|
|
for (int i = 0; i<max_calls; i++) {
|
|
|
|
|
2020-03-29 20:23:56 +02:00
|
|
|
auto *mumcom = new mumble::MumbleCommunicator(*ioService);
|
2017-05-24 22:38:45 +02:00
|
|
|
mumcom->callId = i;
|
|
|
|
|
|
|
|
using namespace std::placeholders;
|
|
|
|
// Passing audio input from SIP to Mumble
|
|
|
|
pjsuaCommunicator.calls[i].onIncomingPcmSamples = std::bind(
|
|
|
|
&mumble::MumbleCommunicator::sendPcmSamples,
|
|
|
|
mumcom,
|
|
|
|
_1, _2);
|
|
|
|
|
|
|
|
// PJ sends text message to Mumble
|
|
|
|
pjsuaCommunicator.calls[i].onStateChange = std::bind(
|
|
|
|
&mumble::MumbleCommunicator::sendTextMessage,
|
|
|
|
mumcom,
|
|
|
|
_1);
|
|
|
|
|
|
|
|
/*
|
|
|
|
// Send mute/deaf to Mumble
|
|
|
|
pjsuaCommunicator.calls[i].onMuteDeafChange = std::bind(
|
|
|
|
&mumble::MumbleCommunicator::mutedeaf,
|
|
|
|
mumcom,
|
|
|
|
_1);
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Send UserState to Mumble
|
|
|
|
pjsuaCommunicator.calls[i].sendUserState = std::bind(
|
2017-05-27 18:19:37 +02:00
|
|
|
static_cast<void(mumble::MumbleCommunicator::*)(mumlib::UserState, bool)>
|
|
|
|
(&mumble::MumbleCommunicator::sendUserState),
|
|
|
|
mumcom,
|
|
|
|
_1, _2);
|
|
|
|
|
|
|
|
// Send UserState to Mumble
|
|
|
|
pjsuaCommunicator.calls[i].sendUserStateStr = std::bind(
|
|
|
|
static_cast<void(mumble::MumbleCommunicator::*)(mumlib::UserState, std::string)>
|
|
|
|
(&mumble::MumbleCommunicator::sendUserState),
|
2017-05-24 22:38:45 +02:00
|
|
|
mumcom,
|
|
|
|
_1, _2);
|
|
|
|
|
|
|
|
// PJ triggers Mumble connect
|
|
|
|
pjsuaCommunicator.calls[i].onConnect = std::bind(
|
|
|
|
&mumble::MumbleCommunicator::onConnect,
|
|
|
|
mumcom);
|
|
|
|
|
|
|
|
// PJ triggers Mumble disconnect
|
|
|
|
pjsuaCommunicator.calls[i].onDisconnect = std::bind(
|
|
|
|
&mumble::MumbleCommunicator::onDisconnect,
|
|
|
|
mumcom);
|
|
|
|
|
|
|
|
// PJ notifies Mumble that Caller Auth is done
|
|
|
|
pjsuaCommunicator.calls[i].onCallerAuth = std::bind(
|
|
|
|
&mumble::MumbleCommunicator::onCallerAuth,
|
|
|
|
mumcom);
|
|
|
|
|
|
|
|
/*
|
|
|
|
// PJ notifies Mumble that Caller Auth is done
|
|
|
|
pjsuaCommunicator.calls[i].onCallerUnauth = std::bind(
|
|
|
|
&mumble::MumbleCommunicator::onCallerUnauth,
|
|
|
|
mumcom);
|
|
|
|
*/
|
|
|
|
|
|
|
|
// PJ notifies Mumble that Caller Auth is done
|
|
|
|
pjsuaCommunicator.calls[i].joinDefaultChannel = std::bind(
|
|
|
|
&mumble::MumbleChannelJoiner::findJoinChannel,
|
|
|
|
&mumbleChannelJoiner,
|
|
|
|
mumcom);
|
|
|
|
|
2017-05-27 22:12:26 +02:00
|
|
|
// PJ notifies Mumble to join other channel
|
|
|
|
pjsuaCommunicator.calls[i].joinOtherChannel = std::bind(
|
|
|
|
&mumble::MumbleChannelJoiner::joinOtherChannel,
|
|
|
|
&mumbleOtherChannelJoiner,
|
|
|
|
mumcom,
|
|
|
|
_1);
|
2017-05-24 22:38:45 +02:00
|
|
|
|
|
|
|
// Passing audio from Mumble to SIP
|
|
|
|
mumcom->onIncomingPcmSamples = std::bind(
|
|
|
|
&sip::PjsuaCommunicator::sendPcmSamples,
|
|
|
|
&pjsuaCommunicator,
|
|
|
|
_1, _2, _3, _4, _5);
|
|
|
|
|
|
|
|
// Handle Channel State messages from Mumble
|
|
|
|
mumcom->onIncomingChannelState = std::bind(
|
|
|
|
&mumble::MumbleChannelJoiner::checkChannel,
|
|
|
|
&mumbleChannelJoiner,
|
|
|
|
_1, _2);
|
|
|
|
|
|
|
|
// Handle Server Sync message from Mumble
|
|
|
|
mumcom->onServerSync = std::bind(
|
|
|
|
&mumble::MumbleChannelJoiner::maybeJoinChannel,
|
|
|
|
&mumbleChannelJoiner,
|
|
|
|
mumcom);
|
|
|
|
|
|
|
|
mumbleConf.user = conf.getString("mumble.user") + '-' + std::to_string(i);
|
2017-05-28 21:16:46 +02:00
|
|
|
try {
|
|
|
|
if ( conf.getBool("mumble.use_certs") ) {
|
|
|
|
mumbleConf.cert_file = mumbleConf.user + "-cert.pem";
|
|
|
|
mumbleConf.privkey_file = mumbleConf.user + "-key.pem";
|
|
|
|
}
|
|
|
|
} catch (...) {
|
|
|
|
logger.info("Client certs not enabled in config");
|
|
|
|
}
|
2017-05-24 22:38:45 +02:00
|
|
|
mumcom->connect(mumbleConf);
|
|
|
|
}
|
2015-11-03 02:13:15 +01:00
|
|
|
|
2015-11-02 23:41:49 +01:00
|
|
|
pjsuaCommunicator.connect(
|
|
|
|
conf.getString("sip.host"),
|
|
|
|
conf.getString("sip.user"),
|
|
|
|
conf.getString("sip.password"),
|
|
|
|
conf.getInt("sip.port"));
|
|
|
|
|
2015-09-29 02:26:45 +02:00
|
|
|
logger.info("Application started.");
|
2015-07-13 18:14:35 +02:00
|
|
|
|
2020-03-29 20:23:56 +02:00
|
|
|
ioService->run();
|
2015-10-16 22:41:37 +02:00
|
|
|
|
2015-07-20 21:09:22 +02:00
|
|
|
return 0;
|
2015-07-13 18:14:35 +02:00
|
|
|
}
|
|
|
|
|