main.cpp 8.2 KB

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