qtipcserver.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
  2. #include <boost/version.hpp>
  3. #if defined(WIN32) && BOOST_VERSION == 104900
  4. #define BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME
  5. #define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
  6. #endif
  7. #include "qtipcserver.h"
  8. #include "guiconstants.h"
  9. #include "ui_interface.h"
  10. #include "util.h"
  11. #include <boost/algorithm/string/predicate.hpp>
  12. #include <boost/date_time/posix_time/posix_time.hpp>
  13. #include <boost/interprocess/ipc/message_queue.hpp>
  14. #include <boost/version.hpp>
  15. #if defined(WIN32) && (!defined(BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME) || !defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) || BOOST_VERSION < 104900)
  16. #warning Compiling without BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME and BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME uncommented in boost/interprocess/detail/tmp_dir_helpers.hpp or using a boost version before 1.49 may have unintended results see svn.boost.org/trac/boost/ticket/5392
  17. #endif
  18. using namespace boost;
  19. using namespace boost::interprocess;
  20. using namespace boost::posix_time;
  21. #if defined MAC_OSX || defined __FreeBSD__
  22. // URI handling not implemented on OSX yet
  23. void ipcScanRelay(int argc, char *argv[]) { }
  24. void ipcInit(int argc, char *argv[]) { }
  25. #else
  26. static void ipcThread2(void* pArg);
  27. static bool ipcScanCmd(int argc, char *argv[], bool fRelay)
  28. {
  29. // Check for URI in argv
  30. bool fSent = false;
  31. for (int i = 1; i < argc; i++)
  32. {
  33. if (boost::algorithm::istarts_with(argv[i], "ecoin:"))
  34. {
  35. const char *strURI = argv[i];
  36. try {
  37. boost::interprocess::message_queue mq(boost::interprocess::open_only, ECOINURI_QUEUE_NAME);
  38. if (mq.try_send(strURI, strlen(strURI), 0))
  39. fSent = true;
  40. else if (fRelay)
  41. break;
  42. }
  43. catch (boost::interprocess::interprocess_exception &ex) {
  44. // don't log the "file not found" exception, because that's normal for
  45. // the first start of the first instance
  46. if (ex.get_error_code() != boost::interprocess::not_found_error || !fRelay)
  47. {
  48. printf("main() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what());
  49. break;
  50. }
  51. }
  52. }
  53. }
  54. return fSent;
  55. }
  56. void ipcScanRelay(int argc, char *argv[])
  57. {
  58. if (ipcScanCmd(argc, argv, true))
  59. exit(0);
  60. }
  61. static void ipcThread(void* pArg)
  62. {
  63. // Make this thread recognisable as the GUI-IPC thread
  64. RenameThread("ecoin-gui-ipc");
  65. try
  66. {
  67. ipcThread2(pArg);
  68. }
  69. catch (std::exception& e) {
  70. PrintExceptionContinue(&e, "ipcThread()");
  71. } catch (...) {
  72. PrintExceptionContinue(NULL, "ipcThread()");
  73. }
  74. printf("ipcThread exited\n");
  75. }
  76. static void ipcThread2(void* pArg)
  77. {
  78. printf("ipcThread started\n");
  79. message_queue* mq = (message_queue*)pArg;
  80. char buffer[MAX_URI_LENGTH + 1] = "";
  81. size_t nSize = 0;
  82. unsigned int nPriority = 0;
  83. while (true)
  84. {
  85. ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(100);
  86. if (mq->timed_receive(&buffer, sizeof(buffer), nSize, nPriority, d))
  87. {
  88. uiInterface.ThreadSafeHandleURI(std::string(buffer, nSize));
  89. Sleep(1000);
  90. }
  91. if (fShutdown)
  92. break;
  93. }
  94. // Remove message queue
  95. message_queue::remove(ECOINURI_QUEUE_NAME);
  96. // Cleanup allocated memory
  97. delete mq;
  98. }
  99. void ipcInit(int argc, char *argv[])
  100. {
  101. message_queue* mq = NULL;
  102. char buffer[MAX_URI_LENGTH + 1] = "";
  103. size_t nSize = 0;
  104. unsigned int nPriority = 0;
  105. try {
  106. mq = new message_queue(open_or_create, ECOINURI_QUEUE_NAME, 2, MAX_URI_LENGTH);
  107. // Make sure we don't lose any ecoin: URIs
  108. for (int i = 0; i < 2; i++)
  109. {
  110. ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1);
  111. if (mq->timed_receive(&buffer, sizeof(buffer), nSize, nPriority, d))
  112. {
  113. uiInterface.ThreadSafeHandleURI(std::string(buffer, nSize));
  114. }
  115. else
  116. break;
  117. }
  118. // Make sure only one ecoin instance is listening
  119. message_queue::remove(ECOINURI_QUEUE_NAME);
  120. delete mq;
  121. mq = new message_queue(open_or_create, ECOINURI_QUEUE_NAME, 2, MAX_URI_LENGTH);
  122. }
  123. catch (interprocess_exception &ex) {
  124. printf("ipcInit() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what());
  125. return;
  126. }
  127. if (!NewThread(ipcThread, mq))
  128. {
  129. delete mq;
  130. return;
  131. }
  132. ipcScanCmd(argc, argv, false);
  133. }
  134. #endif