main.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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. try {
  48. pjsuaCommunicator.pins = conf.getChildren("pins");
  49. } catch (...) {
  50. }
  51. mumble::MumbleCommunicatorConfig mumbleConf;
  52. mumbleConf.host = conf.getString("mumble.host");
  53. mumbleConf.port = conf.getInt("mumble.port");
  54. mumbleConf.user = conf.getString("mumble.user");
  55. mumbleConf.password = conf.getString("mumble.password");
  56. mumbleConf.opusEncoderBitrate = conf.getInt("mumble.opusEncoderBitrate");
  57. /* default to 'false' if not found */
  58. try {
  59. mumbleConf.autodeaf = conf.getBool("mumble.autodeaf");
  60. } catch (...) {
  61. mumbleConf.autodeaf = false;
  62. }
  63. try {
  64. mumbleConf.comment = conf.getString("app.comment");
  65. } catch (...) {
  66. mumbleConf.comment = "";
  67. }
  68. try { pjsuaCommunicator.file_welcome = conf.getString("files.welcome");
  69. } catch (...) {
  70. pjsuaCommunicator.file_welcome = "welcome.wav";
  71. }
  72. try { pjsuaCommunicator.file_prompt_pin = conf.getString("files.prompt_pin");
  73. } catch (...) {
  74. pjsuaCommunicator.file_prompt_pin = "prompt-pin.wav";
  75. }
  76. try { pjsuaCommunicator.file_entering_channel = conf.getString("files.entering_channel");
  77. } catch (...) {
  78. pjsuaCommunicator.file_entering_channel = "entering-channel.wav";
  79. }
  80. try { pjsuaCommunicator.file_announce_new_caller = conf.getString("files.announce_new_caller");
  81. } catch (...) {
  82. pjsuaCommunicator.file_announce_new_caller = "announce-new-caller.wav";
  83. }
  84. try { pjsuaCommunicator.file_invalid_pin = conf.getString("files.invalid_pin");
  85. } catch (...) {
  86. pjsuaCommunicator.file_invalid_pin = "invalid-pin.wav";
  87. }
  88. try { pjsuaCommunicator.file_goodbye = conf.getString("files.goodbye");
  89. } catch (...) {
  90. pjsuaCommunicator.file_goodbye = "goodbye.wav";
  91. }
  92. try { pjsuaCommunicator.file_mute_on = conf.getString("files.mute_on");
  93. } catch (...) {
  94. pjsuaCommunicator.file_mute_on = "mute-on.wav";
  95. }
  96. try { pjsuaCommunicator.file_mute_off = conf.getString("files.mute_off");
  97. } catch (...) {
  98. pjsuaCommunicator.file_mute_off = "mute-off.wav";
  99. }
  100. try { pjsuaCommunicator.file_menu = conf.getString("files.menu");
  101. } catch (...) {
  102. pjsuaCommunicator.file_menu = "menu.wav";
  103. }
  104. std::string defaultChan = conf.getString("mumble.channelNameExpression");
  105. mumble::MumbleChannelJoiner mumbleChannelJoiner(defaultChan);
  106. mumble::MumbleChannelJoiner mumbleOtherChannelJoiner(defaultChan);
  107. for (int i = 0; i<max_calls; i++) {
  108. auto *mumcom = new mumble::MumbleCommunicator(ioService);
  109. mumcom->callId = i;
  110. using namespace std::placeholders;
  111. // Passing audio input from SIP to Mumble
  112. pjsuaCommunicator.calls[i].onIncomingPcmSamples = std::bind(
  113. &mumble::MumbleCommunicator::sendPcmSamples,
  114. mumcom,
  115. _1, _2);
  116. // PJ sends text message to Mumble
  117. pjsuaCommunicator.calls[i].onStateChange = std::bind(
  118. &mumble::MumbleCommunicator::sendTextMessage,
  119. mumcom,
  120. _1);
  121. /*
  122. // Send mute/deaf to Mumble
  123. pjsuaCommunicator.calls[i].onMuteDeafChange = std::bind(
  124. &mumble::MumbleCommunicator::mutedeaf,
  125. mumcom,
  126. _1);
  127. */
  128. // Send UserState to Mumble
  129. pjsuaCommunicator.calls[i].sendUserState = std::bind(
  130. static_cast<void(mumble::MumbleCommunicator::*)(mumlib::UserState, bool)>
  131. (&mumble::MumbleCommunicator::sendUserState),
  132. mumcom,
  133. _1, _2);
  134. // Send UserState to Mumble
  135. pjsuaCommunicator.calls[i].sendUserStateStr = std::bind(
  136. static_cast<void(mumble::MumbleCommunicator::*)(mumlib::UserState, std::string)>
  137. (&mumble::MumbleCommunicator::sendUserState),
  138. mumcom,
  139. _1, _2);
  140. // PJ triggers Mumble connect
  141. pjsuaCommunicator.calls[i].onConnect = std::bind(
  142. &mumble::MumbleCommunicator::onConnect,
  143. mumcom);
  144. // PJ triggers Mumble disconnect
  145. pjsuaCommunicator.calls[i].onDisconnect = std::bind(
  146. &mumble::MumbleCommunicator::onDisconnect,
  147. mumcom);
  148. // PJ notifies Mumble that Caller Auth is done
  149. pjsuaCommunicator.calls[i].onCallerAuth = std::bind(
  150. &mumble::MumbleCommunicator::onCallerAuth,
  151. mumcom);
  152. /*
  153. // PJ notifies Mumble that Caller Auth is done
  154. pjsuaCommunicator.calls[i].onCallerUnauth = std::bind(
  155. &mumble::MumbleCommunicator::onCallerUnauth,
  156. mumcom);
  157. */
  158. // PJ notifies Mumble that Caller Auth is done
  159. pjsuaCommunicator.calls[i].joinDefaultChannel = std::bind(
  160. &mumble::MumbleChannelJoiner::findJoinChannel,
  161. &mumbleChannelJoiner,
  162. mumcom);
  163. // PJ notifies Mumble to join other channel
  164. pjsuaCommunicator.calls[i].joinOtherChannel = std::bind(
  165. &mumble::MumbleChannelJoiner::joinOtherChannel,
  166. &mumbleOtherChannelJoiner,
  167. mumcom,
  168. _1);
  169. // Passing audio from Mumble to SIP
  170. mumcom->onIncomingPcmSamples = std::bind(
  171. &sip::PjsuaCommunicator::sendPcmSamples,
  172. &pjsuaCommunicator,
  173. _1, _2, _3, _4, _5);
  174. // Handle Channel State messages from Mumble
  175. mumcom->onIncomingChannelState = std::bind(
  176. &mumble::MumbleChannelJoiner::checkChannel,
  177. &mumbleChannelJoiner,
  178. _1, _2);
  179. // Handle Server Sync message from Mumble
  180. mumcom->onServerSync = std::bind(
  181. &mumble::MumbleChannelJoiner::maybeJoinChannel,
  182. &mumbleChannelJoiner,
  183. mumcom);
  184. mumbleConf.user = conf.getString("mumble.user") + '-' + std::to_string(i);
  185. try {
  186. if ( conf.getBool("mumble.use_certs") ) {
  187. mumbleConf.cert_file = mumbleConf.user + "-cert.pem";
  188. mumbleConf.privkey_file = mumbleConf.user + "-key.pem";
  189. }
  190. } catch (...) {
  191. logger.info("Client certs not enabled in config");
  192. }
  193. mumcom->connect(mumbleConf);
  194. }
  195. pjsuaCommunicator.connect(
  196. conf.getString("sip.host"),
  197. conf.getString("sip.user"),
  198. conf.getString("sip.password"),
  199. conf.getInt("sip.port"));
  200. logger.info("Application started.");
  201. ioService.run();
  202. return 0;
  203. }