MSVC
[novacoin.git] / src / qt / qtipcserver.cpp
1 // Copyright (c) 2009-2012 The Bitcoin developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5 #include <boost/version.hpp>
6 #if defined(WIN32) && BOOST_VERSION == 104900
7 #define BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME
8 #define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
9 #endif
10
11 #include "qtipcserver.h"
12 #include "guiconstants.h"
13 #include "ui_interface.h"
14 #include "util.h"
15
16 #include <boost/algorithm/string/predicate.hpp>
17 #include <boost/date_time/posix_time/posix_time.hpp>
18 #include <boost/interprocess/ipc/message_queue.hpp>
19 #include <boost/version.hpp>
20
21 #ifndef _MSC_VER
22 #if defined(WIN32) && (!defined(BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME) || !defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) || BOOST_VERSION < 104900)
23 #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
24 #endif
25 #endif
26
27 using namespace boost;
28 using namespace boost::interprocess;
29 using namespace boost::posix_time;
30
31 #if defined MAC_OSX || defined __FreeBSD__
32 // URI handling not implemented on OSX yet
33
34 void ipcScanRelay(int argc, char *argv[]) { }
35 void ipcInit(int argc, char *argv[]) { }
36
37 #else
38
39 static void ipcThread2(void* pArg);
40
41 static bool ipcScanCmd(int argc, char *argv[], bool fRelay)
42 {
43     // Check for URI in argv
44     bool fSent = false;
45     for (int i = 1; i < argc; i++)
46     {
47         if (boost::algorithm::istarts_with(argv[i], "novacoin:"))
48         {
49             const char *strURI = argv[i];
50             try {
51                 boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
52                 if (mq.try_send(strURI, strlen(strURI), 0))
53                     fSent = true;
54                 else if (fRelay)
55                     break;
56             }
57             catch (boost::interprocess::interprocess_exception &ex) {
58                 // don't log the "file not found" exception, because that's normal for
59                 // the first start of the first instance
60                 if (ex.get_error_code() != boost::interprocess::not_found_error || !fRelay)
61                 {
62                     printf("main() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what());
63                     break;
64                 }
65             }
66         }
67     }
68     return fSent;
69 }
70
71 void ipcScanRelay(int argc, char *argv[])
72 {
73     if (ipcScanCmd(argc, argv, true))
74         exit(0);
75 }
76
77 static void ipcThread(void* pArg)
78 {
79     // Make this thread recognisable as the GUI-IPC thread
80     RenameThread("novacoin-gui-ipc");
81         
82     try
83     {
84         ipcThread2(pArg);
85     }
86     catch (std::exception& e) {
87         PrintExceptionContinue(&e, "ipcThread()");
88     } catch (...) {
89         PrintExceptionContinue(NULL, "ipcThread()");
90     }
91     printf("ipcThread exited\n");
92 }
93
94 static void ipcThread2(void* pArg)
95 {
96     printf("ipcThread started\n");
97
98     message_queue* mq = (message_queue*)pArg;
99     char buffer[MAX_URI_LENGTH + 1] = "";
100     size_t nSize = 0;
101     unsigned int nPriority = 0;
102
103     while (true)
104     {
105         ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(100);
106         if (mq->timed_receive(&buffer, sizeof(buffer), nSize, nPriority, d))
107         {
108             uiInterface.ThreadSafeHandleURI(std::string(buffer, nSize));
109             Sleep(1000);
110         }
111
112         if (fShutdown)
113             break;
114     }
115
116     // Remove message queue
117     message_queue::remove(BITCOINURI_QUEUE_NAME);
118     // Cleanup allocated memory
119     delete mq;
120 }
121
122 void ipcInit(int argc, char *argv[])
123 {
124     message_queue* mq = NULL;
125     char buffer[MAX_URI_LENGTH + 1] = "";
126     size_t nSize = 0;
127     unsigned int nPriority = 0;
128
129     try {
130         mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, MAX_URI_LENGTH);
131
132         // Make sure we don't lose any bitcoin: URIs
133         for (int i = 0; i < 2; i++)
134         {
135             ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1);
136             if (mq->timed_receive(&buffer, sizeof(buffer), nSize, nPriority, d))
137             {
138                 uiInterface.ThreadSafeHandleURI(std::string(buffer, nSize));
139             }
140             else
141                 break;
142         }
143
144         // Make sure only one bitcoin instance is listening
145         message_queue::remove(BITCOINURI_QUEUE_NAME);
146         delete mq;
147
148         mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, MAX_URI_LENGTH);
149     }
150     catch (interprocess_exception &ex) {
151         printf("ipcInit() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what());
152         return;
153     }
154
155     if (!NewThread(ipcThread, mq))
156     {
157         delete mq;
158         return;
159     }
160
161     ipcScanCmd(argc, argv, false);
162 }
163
164 #endif