diff --git a/Configuration.cpp b/Configuration.cpp index 0c94a8a..c93b9e0 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -3,6 +3,7 @@ #include #include #include +#include using namespace config; @@ -50,4 +51,15 @@ std::string config::Configuration::getString(const std::string &property) { return get(impl->ptree, property); } +// TODO: return set +std::unordered_map config::Configuration::getChildren(const std::string &property) { + std::unordered_map pins; + BOOST_FOREACH(boost::property_tree::ptree::value_type &v, + impl->ptree.get_child(property)) { + //pins[v.first.data()] = get(impl->ptree, property + "." + v.second.data()); + pins[v.first.data()] = v.second.data(); + } + return pins; +} + diff --git a/Configuration.hpp b/Configuration.hpp index 8c38acb..c36a87c 100644 --- a/Configuration.hpp +++ b/Configuration.hpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace config { @@ -31,6 +32,8 @@ namespace config { std::string getString(const std::string &property); + std::unordered_map getChildren(const std::string &property); + private: ConfigurationImpl *impl; }; diff --git a/MumbleChannelJoiner.cpp b/MumbleChannelJoiner.cpp index 4f58a7c..d3d33b4 100644 --- a/MumbleChannelJoiner.cpp +++ b/MumbleChannelJoiner.cpp @@ -50,3 +50,9 @@ void mumble::MumbleChannelJoiner::findJoinChannel(mumble::MumbleCommunicator *mc } } +void mumble::MumbleChannelJoiner::joinOtherChannel(mumble::MumbleCommunicator *mc, std::string channelNameRegex) { + this->channelNameRegex = boost::regex(channelNameRegex); + findJoinChannel(mc); +} + + diff --git a/MumbleChannelJoiner.hpp b/MumbleChannelJoiner.hpp index 1de5867..156665e 100644 --- a/MumbleChannelJoiner.hpp +++ b/MumbleChannelJoiner.hpp @@ -22,6 +22,7 @@ namespace mumble { void checkChannel(std::string channel_name, int channel_id); void maybeJoinChannel(mumble::MumbleCommunicator *mc); void findJoinChannel(mumble::MumbleCommunicator *mc); + void joinOtherChannel(mumble::MumbleCommunicator *mc, std::string channelNameRegex); private: log4cpp::Category &logger; diff --git a/PjsuaCommunicator.cpp b/PjsuaCommunicator.cpp index efadae8..2046fc3 100644 --- a/PjsuaCommunicator.cpp +++ b/PjsuaCommunicator.cpp @@ -121,8 +121,8 @@ namespace sip { class _Account : public pj::Account { public: - _Account(sip::PjsuaCommunicator &comm) - : communicator(comm) { } + _Account(sip::PjsuaCommunicator &comm, int max_calls) + : communicator(comm) { this->max_calls = max_calls; } virtual void onRegState(pj::OnRegStateParam &prm) override; @@ -131,7 +131,8 @@ namespace sip { private: sip::PjsuaCommunicator &communicator; - bool available = true; + int active_calls = 0; + int max_calls; friend class _Call; }; @@ -166,7 +167,7 @@ namespace sip { * if no pin is set, go ahead and turn off mute/deaf * otherwise, wait for pin to be entered */ - if ( communicator.caller_pin.length() == 0 ) { + if ( communicator.pins.size() == 0 ) { // No PIN set... enter DTMF root menu and turn off mute/deaf communicator.dtmf_mode = DTMF_MODE_ROOT; // turning off mute automatically turns off deaf @@ -185,7 +186,11 @@ namespace sip { } else if (ci.state == PJSIP_INV_STATE_DISCONNECTED) { auto &acc = dynamic_cast<_Account &>(account); - if (not acc.available) { + /* + * Not sure why we check acc.available, but with multi-call + * functionality, this check doesn't work. + */ + //if (not acc.available) { auto msgText = "Call from " + address + " finished."; communicator.calls[ci.id].mixer->clear(); @@ -198,8 +203,9 @@ namespace sip { communicator.calls[ci.id].onDisconnect(); - acc.available = true; - } + //acc.available = true; + acc.active_calls--; + //} delete this; } else { @@ -221,7 +227,7 @@ namespace sip { communicator.calls[ci.id].media->startTransmit(*aud_med); aud_med->startTransmit(*communicator.calls[ci.id].media); } else if (ci.media[0].status == PJSUA_CALL_MEDIA_NONE) { - dynamic_cast<_Account &>(account).available = true; + dynamic_cast<_Account &>(account).active_calls++; } } @@ -293,6 +299,7 @@ namespace sip { pj::CallOpParam param; auto ci = getInfo(); + std::string chanName; /* * DTMF CALLER MENU @@ -308,11 +315,15 @@ namespace sip { /* * When user presses '#', test PIN entry */ - if ( communicator.caller_pin.length() > 0 ) { - if ( communicator.got_dtmf == communicator.caller_pin ) { + if ( communicator.pins.size() > 0 ) { + if ( communicator.pins.count(communicator.got_dtmf) > 0 ) { communicator.logger.info("Caller entered correct PIN"); communicator.dtmf_mode = DTMF_MODE_ROOT; - communicator.calls[ci.id].joinAuthChannel(); + communicator.logger.notice("MYDEBUG: %s:%s", + communicator.got_dtmf.c_str(), + communicator.pins[communicator.got_dtmf].c_str()); + communicator.calls[ci.id].joinOtherChannel( + communicator.pins[communicator.got_dtmf]); this->playAudioFile(communicator.file_entering_channel); communicator.calls[ci.id].sendUserState(mumlib::UserState::SELF_MUTE, false); @@ -386,12 +397,23 @@ namespace sip { this->playAudioFile(communicator.file_mute_off); communicator.calls[ci.id].sendUserState(mumlib::UserState::SELF_MUTE, false); break; - case '0': + case '9': + if ( communicator.pins.size() > 0 ) { + communicator.dtmf_mode = DTMF_MODE_UNAUTH; + communicator.calls[ci.id].sendUserState(mumlib::UserState::SELF_DEAF, true); + communicator.calls[ci.id].joinDefaultChannel(); + this->playAudioFile(communicator.file_prompt_pin); + } else { + // we should have a 'not supported' message + } + break; + case '0': // block these for the menu itself + case '*': + default: // play menu + communicator.logger.info("Unsupported DTMF digit '%s' in state STAR", prm.digit.c_str()); this->playAudioFile(communicator.file_menu); break; - default: - communicator.logger.info("Unsupported DTMF digit '%s' in state STAR", prm.digit.c_str()); } /* * In any case, switch back to root after one digit @@ -422,17 +444,13 @@ namespace sip { if (communicator.uriValidator.validateUri(uri)) { - if (available) { + if (active_calls < max_calls) { param.statusCode = PJSIP_SC_OK; - available = false; + active_calls++; } else { - /* - * EXPERIMENT WITH MULTI-LINE - */ - communicator.logger.info("MULTI-LINE Incoming call from %s.", uri.c_str()); + communicator.logger.notice("BUSY - reject incoming call from %s.", uri.c_str()); param.statusCode = PJSIP_SC_OK; - available = false; - //param.statusCode = PJSIP_SC_BUSY_EVERYWHERE; + param.statusCode = PJSIP_SC_BUSY_EVERYWHERE; } call->answer(param); @@ -450,6 +468,7 @@ sip::PjsuaCommunicator::PjsuaCommunicator(IncomingConnectionValidator &validator uriValidator(validator) { logWriter.reset(new sip::_LogWriter(pjsuaLogger)); + max_calls = maxCalls; endpoint.libCreate(); @@ -551,7 +570,7 @@ void sip::PjsuaCommunicator::registerAccount(string host, string user, string pa accountConfig.sipConfig.authCreds.push_back(cred); logger.info("Registering account for URI: %s.", uri.c_str()); - account.reset(new _Account(*this)); + account.reset(new _Account(*this, max_calls)); account->create(accountConfig); } diff --git a/PjsuaCommunicator.hpp b/PjsuaCommunicator.hpp index c42c1dc..72ce42b 100644 --- a/PjsuaCommunicator.hpp +++ b/PjsuaCommunicator.hpp @@ -80,7 +80,8 @@ namespace sip { std::function onConnect; std::function onDisconnect; std::function onCallerAuth; - std::function joinAuthChannel; + std::function joinAuthChannel; // DEPRECATE ? + std::function joinOtherChannel; std::function joinDefaultChannel; }; @@ -114,6 +115,7 @@ namespace sip { std::string file_mute_on; std::string file_mute_off; std::string file_menu; + int max_calls; // TODO: move these to private? std::string got_dtmf; @@ -126,6 +128,8 @@ namespace sip { call calls[MY_MAX_CALLS]; + std::unordered_map pins; + private: log4cpp::Category &logger; log4cpp::Category &pjsuaLogger; diff --git a/main.cpp b/main.cpp index 41a83c9..789a3a8 100644 --- a/main.cpp +++ b/main.cpp @@ -60,6 +60,11 @@ int main(int argc, char *argv[]) { 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"); @@ -79,19 +84,6 @@ int main(int argc, char *argv[]) { mumbleConf.comment = ""; } - try { - mumbleConf.authchan = conf.getString("mumble.channelAuthExpression"); - } catch (...) { - mumbleConf.authchan = ""; - } - - /* default to */ - try { - pjsuaCommunicator.caller_pin = conf.getString("app.caller_pin"); - } catch (...) { - pjsuaCommunicator.caller_pin = ""; - } - try { pjsuaCommunicator.file_welcome = conf.getString("files.welcome"); } catch (...) { pjsuaCommunicator.file_welcome = "welcome.wav"; @@ -137,23 +129,10 @@ int main(int argc, char *argv[]) { pjsuaCommunicator.file_menu = "menu.wav"; } - /* If the channelUnauthExpression is set, use this as the default - * channel and use channelNameExpression for the authchan. Otherwise, - * use the channelNameExpression for the default. - */ std::string defaultChan = conf.getString("mumble.channelNameExpression"); - std::string authChan = ""; - - if ( pjsuaCommunicator.caller_pin.size() > 0 ) { - try { - authChan = conf.getString("mumble.channelAuthExpression"); - } catch (...) { - // defaultChan = conf.getString("mumble.channelNameExpression"); - } - } mumble::MumbleChannelJoiner mumbleChannelJoiner(defaultChan); - mumble::MumbleChannelJoiner mumbleAuthChannelJoiner(authChan); + mumble::MumbleChannelJoiner mumbleOtherChannelJoiner(defaultChan); for (int i = 0; ionIncomingPcmSamples = std::bind( diff --git a/media/menu.msg b/media/menu.msg index 7644a28..6472a04 100644 --- a/media/menu.msg +++ b/media/menu.msg @@ -1,3 +1,3 @@ -Press star one for status. Press star five to mute. Press star six to un-mute. +Press star nine to change channel. diff --git a/media/menu.wav b/media/menu.wav index 1a9df4e..75b5915 100644 Binary files a/media/menu.wav and b/media/menu.wav differ