winmain.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * Copyright (C) 2004-2017 Savoir-faire Linux Inc.
  3. *
  4. * Author: Edric Milaret <edric.ladent-milaret@savoirfairelinux.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. */
  20. #include <iostream>
  21. #include <thread>
  22. #include <cstring>
  23. #include <signal.h>
  24. #include <getopt.h>
  25. #include <string>
  26. #include "dring.h"
  27. #include "callmanager_interface.h"
  28. #include "configurationmanager_interface.h"
  29. #include "presencemanager_interface.h"
  30. #ifdef RING_VIDEO
  31. #include "videomanager_interface.h"
  32. #endif
  33. #include "fileutils.h"
  34. #include <windows.h>
  35. using namespace std::placeholders;
  36. bool isActive = false;
  37. static int ringFlags = 0;
  38. bool loop = true;
  39. static void
  40. print_title()
  41. {
  42. std::cout
  43. << "Ring Daemon " << DRing::version()
  44. << ", by Savoir-faire Linux 2004-2017" << std::endl
  45. << "http://www.ring.cx/" << std::endl
  46. #ifdef RING_VIDEO
  47. << "[Video support enabled]" << std::endl
  48. #endif
  49. << std::endl;
  50. }
  51. static void
  52. print_usage()
  53. {
  54. std::cout << std::endl <<
  55. "-c, --console \t- Log in console (instead of syslog)" << std::endl <<
  56. "-d, --debug \t- Debug mode (more verbose)" << std::endl <<
  57. "-p, --persistent \t- Stay alive after client quits" << std::endl <<
  58. "--auto-answer \t- Force automatic answer to incoming calls" << std::endl <<
  59. "-h, --help \t- Print help" << std::endl;
  60. }
  61. // Parse command line arguments, setting debug options or printing a help
  62. // message accordingly.
  63. // returns true if we should quit (i.e. help was printed), false otherwise
  64. static bool
  65. parse_args(int argc, char *argv[], bool& persistent)
  66. {
  67. int consoleFlag = false;
  68. int debugFlag = false;
  69. int helpFlag = false;
  70. int versionFlag = false;
  71. int autoAnswer = false;
  72. const struct option long_options[] = {
  73. /* These options set a flag. */
  74. {"debug", no_argument, NULL, 'd'},
  75. {"console", no_argument, NULL, 'c'},
  76. {"persistent", no_argument, NULL, 'p'},
  77. {"help", no_argument, NULL, 'h'},
  78. {"version", no_argument, NULL, 'v'},
  79. {"auto-answer", no_argument, &autoAnswer, true},
  80. {0, 0, 0, 0} /* Sentinel */
  81. };
  82. while (true) {
  83. /* getopt_long stores the option index here. */
  84. int option_index = 0;
  85. auto c = getopt_long(argc, argv, "dcphv", long_options, &option_index);
  86. // end of the options
  87. if (c == -1)
  88. break;
  89. switch (c) {
  90. case 'd':
  91. debugFlag = true;
  92. break;
  93. case 'c':
  94. consoleFlag = true;
  95. break;
  96. case 'p':
  97. persistent = true;
  98. break;
  99. case 'h':
  100. case '?':
  101. helpFlag = true;
  102. break;
  103. case 'v':
  104. versionFlag = true;
  105. break;
  106. default:
  107. break;
  108. }
  109. }
  110. if (helpFlag) {
  111. print_usage();
  112. return true;
  113. }
  114. if (versionFlag) {
  115. // We've always print the title/version, so we can just exit
  116. return true;
  117. }
  118. if (consoleFlag)
  119. ringFlags |= DRing::DRING_FLAG_CONSOLE_LOG;
  120. if (debugFlag)
  121. ringFlags |= DRing::DRING_FLAG_DEBUG;
  122. if (autoAnswer)
  123. ringFlags |= DRing::DRING_FLAG_AUTOANSWER;
  124. return false;
  125. }
  126. void
  127. IncomingCall(const std::string& accountId,
  128. const std::string& callId, const std::string& message)
  129. {
  130. (void) accountId;
  131. (void) message;
  132. if (not isActive) {
  133. DRing::accept(callId);
  134. isActive = true;
  135. } else
  136. DRing::refuse(callId);
  137. }
  138. static int
  139. run()
  140. {
  141. using SharedCallback = std::shared_ptr<DRing::CallbackWrapperBase>;
  142. DRing::init(static_cast<DRing::InitFlag>(ringFlags));
  143. std::map<std::string, SharedCallback> callHandlers;
  144. callHandlers.insert(DRing::exportable_callback<DRing::CallSignal::IncomingCall>
  145. (std::bind(&IncomingCall, _1, _2, _3)));
  146. registerCallHandlers(callHandlers);
  147. if (!DRing::start())
  148. return -1;
  149. while (loop) {
  150. DRing::pollEvents();
  151. Sleep(1000); // milliseconds
  152. }
  153. DRing::fini();
  154. return 0;
  155. }
  156. static void
  157. interrupt()
  158. {
  159. loop = false;
  160. }
  161. static void
  162. signal_handler(int code)
  163. {
  164. std::cerr << "Caught signal " << code
  165. << ", terminating..." << std::endl;
  166. // Unset signal handlers
  167. signal(SIGINT, SIG_DFL);
  168. signal(SIGTERM, SIG_DFL);
  169. interrupt();
  170. }
  171. int
  172. main(int argc, char *argv [])
  173. {
  174. // make a copy as we don't want to modify argv[0], copy it to a vector to
  175. // guarantee that memory is correctly managed/exception safe
  176. std::string programName {argv[0]};
  177. std::vector<char> writable(programName.size() + 1);
  178. std::copy(std::begin(programName), std::end(programName),std::begin(writable));
  179. ring::fileutils::set_program_dir(writable.data());
  180. print_title();
  181. bool persistent = false;
  182. if (parse_args(argc, argv, persistent))
  183. return 0;
  184. // TODO: Block signals for all threads but the main thread, decide how/if we should
  185. // handle other signals
  186. signal(SIGINT, signal_handler);
  187. signal(SIGTERM, signal_handler);
  188. return run();
  189. }