main.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. #include "PjsuaCommunicator.hpp"
  2. #include "MumbleCommunicator.hpp"
  3. #include "IncomingConnectionValidator.hpp"
  4. #include "MumbleChannelJoiner.hpp"
  5. #include "Configuration.hpp"
  6. #include <log4cpp/FileAppender.hh>
  7. #include <log4cpp/OstreamAppender.hh>
  8. #include <log4cpp/PatternLayout.hh>
  9. #include <execinfo.h>
  10. #include <memory>
  11. #include "main.hpp"
  12. namespace {
  13. std::weak_ptr<boost::asio::io_service> g_ioService;
  14. /*
  15. * Code from http://stackoverflow.com/a/77336/5419223
  16. */
  17. void sigsegv_handler(int sig) {
  18. constexpr int STACK_DEPTH = 10;
  19. void *array[STACK_DEPTH];
  20. size_t size = backtrace(array, STACK_DEPTH);
  21. fprintf(stderr, "ERROR: signal %d:\n", sig);
  22. backtrace_symbols_fd(array, size, STDERR_FILENO);
  23. exit(1);
  24. }
  25. void sigint_handler(int sig)
  26. {
  27. fprintf(stderr, "Caught SIGINT, trying to stop\n");
  28. if (auto io = g_ioService.lock()) {
  29. io->stop();
  30. }
  31. }
  32. void SetupSignalHandlers()
  33. {
  34. struct sigaction sigIntHandler;
  35. sigIntHandler.sa_handler = sigsegv_handler;
  36. sigemptyset(&sigIntHandler.sa_mask);
  37. sigIntHandler.sa_flags = 0;
  38. sigaction(SIGSEGV, &sigIntHandler, NULL);
  39. memset(&sigIntHandler, 0, sizeof(sigIntHandler));
  40. sigIntHandler.sa_handler = sigint_handler;
  41. sigemptyset(&sigIntHandler.sa_mask);
  42. sigIntHandler.sa_flags = 0;
  43. sigaction(SIGINT, &sigIntHandler, NULL);
  44. }
  45. } // anonymous namespace
  46. int main(int argc, char *argv[]) {
  47. SetupSignalHandlers();
  48. int max_calls;
  49. log4cpp::OstreamAppender appender("console", &std::cout);
  50. log4cpp::PatternLayout layout;
  51. layout.setConversionPattern("%d [%p] %c: %m%n");
  52. appender.setLayout(&layout);
  53. log4cpp::Category &logger = log4cpp::Category::getRoot();
  54. logger.setPriority(log4cpp::Priority::DEBUG);
  55. //logger.setPriority(log4cpp::Priority::NOTICE);
  56. logger.addAppender(appender);
  57. if (argc == 1) {
  58. logger.crit("No configuration file provided. Use %s {config file}", argv[0]);
  59. std::exit(1);
  60. }
  61. config::Configuration conf(argv[1]);
  62. logger.setPriority(log4cpp::Priority::getPriorityValue(conf.getString("general.logLevel")));
  63. sip::IncomingConnectionValidator connectionValidator(conf.getString("sip.validUriExpression"));
  64. auto ioService = std::make_shared<boost::asio::io_service>();
  65. g_ioService = ioService;
  66. try {
  67. max_calls = conf.getInt("sip.max_calls");
  68. } catch (...) {
  69. max_calls = 1;
  70. }
  71. sip::PjsuaCommunicator pjsuaCommunicator(connectionValidator, conf.getInt("sip.frameLength"), max_calls);
  72. try {
  73. pjsuaCommunicator.pins = conf.getChildren("pins");
  74. } catch (...) {
  75. }
  76. mumble::MumbleCommunicatorConfig mumbleConf;
  77. mumbleConf.host = conf.getString("mumble.host");
  78. mumbleConf.port = conf.getInt("mumble.port");
  79. mumbleConf.user = conf.getString("mumble.user");
  80. mumbleConf.password = conf.getString("mumble.password");
  81. mumbleConf.opusEncoderBitrate = conf.getInt("mumble.opusEncoderBitrate");
  82. /* default to 'false' if not found */
  83. try {
  84. mumbleConf.autodeaf = conf.getBool("mumble.autodeaf");
  85. } catch (...) {
  86. mumbleConf.autodeaf = false;
  87. }
  88. try {
  89. mumbleConf.comment = conf.getString("app.comment");
  90. } catch (...) {
  91. mumbleConf.comment = "";
  92. }
  93. try { pjsuaCommunicator.file_welcome = conf.getString("files.welcome");
  94. } catch (...) {
  95. pjsuaCommunicator.file_welcome = "welcome.wav";
  96. }
  97. try { pjsuaCommunicator.file_prompt_pin = conf.getString("files.prompt_pin");
  98. } catch (...) {
  99. pjsuaCommunicator.file_prompt_pin = "prompt-pin.wav";
  100. }
  101. try { pjsuaCommunicator.file_entering_channel = conf.getString("files.entering_channel");
  102. } catch (...) {
  103. pjsuaCommunicator.file_entering_channel = "entering-channel.wav";
  104. }
  105. try { pjsuaCommunicator.file_announce_new_caller = conf.getString("files.announce_new_caller");
  106. } catch (...) {
  107. pjsuaCommunicator.file_announce_new_caller = "announce-new-caller.wav";
  108. }
  109. try { pjsuaCommunicator.file_invalid_pin = conf.getString("files.invalid_pin");
  110. } catch (...) {
  111. pjsuaCommunicator.file_invalid_pin = "invalid-pin.wav";
  112. }
  113. try { pjsuaCommunicator.file_goodbye = conf.getString("files.goodbye");
  114. } catch (...) {
  115. pjsuaCommunicator.file_goodbye = "goodbye.wav";
  116. }
  117. try { pjsuaCommunicator.file_mute_on = conf.getString("files.mute_on");
  118. } catch (...) {
  119. pjsuaCommunicator.file_mute_on = "mute-on.wav";
  120. }
  121. try { pjsuaCommunicator.file_mute_off = conf.getString("files.mute_off");
  122. } catch (...) {
  123. pjsuaCommunicator.file_mute_off = "mute-off.wav";
  124. }
  125. try { pjsuaCommunicator.file_menu = conf.getString("files.menu");
  126. } catch (...) {
  127. pjsuaCommunicator.file_menu = "menu.wav";
  128. }
  129. std::string defaultChan = conf.getString("mumble.channelNameExpression");
  130. mumble::MumbleChannelJoiner mumbleChannelJoiner(defaultChan);
  131. mumble::MumbleChannelJoiner mumbleOtherChannelJoiner(defaultChan);
  132. for (int i = 0; i<max_calls; i++) {
  133. auto *mumcom = new mumble::MumbleCommunicator(*ioService);
  134. mumcom->callId = i;
  135. using namespace std::placeholders;
  136. // Passing audio input from SIP to Mumble
  137. pjsuaCommunicator.calls[i].onIncomingPcmSamples = std::bind(
  138. &mumble::MumbleCommunicator::sendPcmSamples,
  139. mumcom,
  140. _1, _2);
  141. // PJ sends text message to Mumble
  142. pjsuaCommunicator.calls[i].onStateChange = std::bind(
  143. &mumble::MumbleCommunicator::sendTextMessage,
  144. mumcom,
  145. _1);
  146. /*
  147. // Send mute/deaf to Mumble
  148. pjsuaCommunicator.calls[i].onMuteDeafChange = std::bind(
  149. &mumble::MumbleCommunicator::mutedeaf,
  150. mumcom,
  151. _1);
  152. */
  153. // Send UserState to Mumble
  154. pjsuaCommunicator.calls[i].sendUserState = std::bind(
  155. static_cast<void(mumble::MumbleCommunicator::*)(mumlib::UserState, bool)>
  156. (&mumble::MumbleCommunicator::sendUserState),
  157. mumcom,
  158. _1, _2);
  159. // Send UserState to Mumble
  160. pjsuaCommunicator.calls[i].sendUserStateStr = std::bind(
  161. static_cast<void(mumble::MumbleCommunicator::*)(mumlib::UserState, std::string)>
  162. (&mumble::MumbleCommunicator::sendUserState),
  163. mumcom,
  164. _1, _2);
  165. // PJ triggers Mumble connect
  166. pjsuaCommunicator.calls[i].onConnect = std::bind(
  167. &mumble::MumbleCommunicator::onConnect,
  168. mumcom);
  169. // PJ triggers Mumble disconnect
  170. pjsuaCommunicator.calls[i].onDisconnect = std::bind(
  171. &mumble::MumbleCommunicator::onDisconnect,
  172. mumcom);
  173. // PJ notifies Mumble that Caller Auth is done
  174. pjsuaCommunicator.calls[i].onCallerAuth = std::bind(
  175. &mumble::MumbleCommunicator::onCallerAuth,
  176. mumcom);
  177. /*
  178. // PJ notifies Mumble that Caller Auth is done
  179. pjsuaCommunicator.calls[i].onCallerUnauth = std::bind(
  180. &mumble::MumbleCommunicator::onCallerUnauth,
  181. mumcom);
  182. */
  183. // PJ notifies Mumble that Caller Auth is done
  184. pjsuaCommunicator.calls[i].joinDefaultChannel = std::bind(
  185. &mumble::MumbleChannelJoiner::findJoinChannel,
  186. &mumbleChannelJoiner,
  187. mumcom);
  188. // PJ notifies Mumble to join other channel
  189. pjsuaCommunicator.calls[i].joinOtherChannel = std::bind(
  190. &mumble::MumbleChannelJoiner::joinOtherChannel,
  191. &mumbleOtherChannelJoiner,
  192. mumcom,
  193. _1);
  194. // Passing audio from Mumble to SIP
  195. mumcom->onIncomingPcmSamples = std::bind(
  196. &sip::PjsuaCommunicator::sendPcmSamples,
  197. &pjsuaCommunicator,
  198. _1, _2, _3, _4, _5);
  199. // Handle Channel State messages from Mumble
  200. mumcom->onIncomingChannelState = std::bind(
  201. &mumble::MumbleChannelJoiner::checkChannel,
  202. &mumbleChannelJoiner,
  203. _1, _2);
  204. // Handle Server Sync message from Mumble
  205. mumcom->onServerSync = std::bind(
  206. &mumble::MumbleChannelJoiner::maybeJoinChannel,
  207. &mumbleChannelJoiner,
  208. mumcom);
  209. mumbleConf.user = conf.getString("mumble.user") + '-' + std::to_string(i);
  210. try {
  211. if ( conf.getBool("mumble.use_certs") ) {
  212. mumbleConf.cert_file = mumbleConf.user + "-cert.pem";
  213. mumbleConf.privkey_file = mumbleConf.user + "-key.pem";
  214. }
  215. } catch (...) {
  216. logger.info("Client certs not enabled in config");
  217. }
  218. mumcom->connect(mumbleConf);
  219. }
  220. pjsuaCommunicator.connect(
  221. conf.getString("sip.host"),
  222. conf.getString("sip.user"),
  223. conf.getString("sip.password"),
  224. conf.getInt("sip.port"));
  225. logger.info("Application started.");
  226. ioService->run();
  227. return 0;
  228. }