#include "PjsuaCommunicator.hpp" #include "MumbleCommunicator.hpp" #include "IncomingConnectionValidator.hpp" #include "MumbleChannelJoiner.hpp" #include "Configuration.hpp" #include #include #include #include #include #include "main.hpp" namespace { std::weak_ptr g_ioService; /* * Code from http://stackoverflow.com/a/77336/5419223 */ void sigsegv_handler(int sig) { 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); } 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 int main(int argc, char *argv[]) { SetupSignalHandlers(); int max_calls; log4cpp::OstreamAppender appender("console", &std::cout); log4cpp::PatternLayout layout; layout.setConversionPattern("%d [%p] %c: %m%n"); appender.setLayout(&layout); log4cpp::Category &logger = log4cpp::Category::getRoot(); logger.setPriority(log4cpp::Priority::DEBUG); //logger.setPriority(log4cpp::Priority::NOTICE); logger.addAppender(appender); if (argc == 1) { logger.crit("No configuration file provided. Use %s {config file}", argv[0]); std::exit(1); } config::Configuration conf(argv[1]); logger.setPriority(log4cpp::Priority::getPriorityValue(conf.getString("general.logLevel"))); sip::IncomingConnectionValidator connectionValidator(conf.getString("sip.validUriExpression")); auto ioService = std::make_shared(); g_ioService = ioService; try { max_calls = conf.getInt("sip.max_calls"); } catch (...) { max_calls = 1; } sip::PjsuaCommunicator pjsuaCommunicator(connectionValidator, conf.getInt("sip.frameLength"), max_calls); try { pjsuaCommunicator.pins = conf.getChildren("pins"); } catch (...) { } 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"); /* default to 'false' if not found */ try { mumbleConf.autodeaf = conf.getBool("mumble.autodeaf"); } catch (...) { mumbleConf.autodeaf = false; } try { mumbleConf.comment = conf.getString("app.comment"); } catch (...) { mumbleConf.comment = ""; } try { pjsuaCommunicator.file_welcome = conf.getString("files.welcome"); } catch (...) { pjsuaCommunicator.file_welcome = "welcome.wav"; } try { pjsuaCommunicator.file_prompt_pin = conf.getString("files.prompt_pin"); } catch (...) { pjsuaCommunicator.file_prompt_pin = "prompt-pin.wav"; } try { pjsuaCommunicator.file_entering_channel = conf.getString("files.entering_channel"); } catch (...) { pjsuaCommunicator.file_entering_channel = "entering-channel.wav"; } try { pjsuaCommunicator.file_announce_new_caller = conf.getString("files.announce_new_caller"); } catch (...) { pjsuaCommunicator.file_announce_new_caller = "announce-new-caller.wav"; } try { pjsuaCommunicator.file_invalid_pin = conf.getString("files.invalid_pin"); } catch (...) { pjsuaCommunicator.file_invalid_pin = "invalid-pin.wav"; } try { pjsuaCommunicator.file_goodbye = conf.getString("files.goodbye"); } catch (...) { pjsuaCommunicator.file_goodbye = "goodbye.wav"; } try { pjsuaCommunicator.file_mute_on = conf.getString("files.mute_on"); } catch (...) { pjsuaCommunicator.file_mute_on = "mute-on.wav"; } try { pjsuaCommunicator.file_mute_off = conf.getString("files.mute_off"); } catch (...) { pjsuaCommunicator.file_mute_off = "mute-off.wav"; } try { pjsuaCommunicator.file_menu = conf.getString("files.menu"); } catch (...) { pjsuaCommunicator.file_menu = "menu.wav"; } std::string defaultChan = conf.getString("mumble.channelNameExpression"); mumble::MumbleChannelJoiner mumbleChannelJoiner(defaultChan); mumble::MumbleChannelJoiner mumbleOtherChannelJoiner(defaultChan); for (int i = 0; icallId = 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( static_cast (&mumble::MumbleCommunicator::sendUserState), mumcom, _1, _2); // Send UserState to Mumble pjsuaCommunicator.calls[i].sendUserStateStr = std::bind( static_cast (&mumble::MumbleCommunicator::sendUserState), 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); // PJ notifies Mumble to join other channel pjsuaCommunicator.calls[i].joinOtherChannel = std::bind( &mumble::MumbleChannelJoiner::joinOtherChannel, &mumbleOtherChannelJoiner, mumcom, _1); // 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); 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"); } mumcom->connect(mumbleConf); } pjsuaCommunicator.connect( conf.getString("sip.host"), conf.getString("sip.user"), conf.getString("sip.password"), conf.getInt("sip.port")); logger.info("Application started."); ioService->run(); return 0; }