// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
-// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <boost/algorithm/string.hpp>
-#include <boost/interprocess/ipc/message_queue.hpp>
-#include <boost/tokenizer.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/version.hpp>
+#if defined(WIN32) && BOOST_VERSION == 104900
+#define BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME
+#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
+#endif
-#include "util.h"
#include "qtipcserver.h"
+#include "guiconstants.h"
+#include "ui_interface.h"
+#include "util.h"
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/interprocess/ipc/message_queue.hpp>
+#include <boost/version.hpp>
+
+#ifndef _MSC_VER
+#if defined(WIN32) && (!defined(BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME) || !defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) || BOOST_VERSION < 104900)
+#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
+#endif
+#endif
+
+using namespace boost;
using namespace boost::interprocess;
using namespace boost::posix_time;
-using namespace boost;
-using namespace std;
-void ipcShutdown()
+#if defined MAC_OSX || defined __FreeBSD__
+// URI handling not implemented on OSX yet
+
+void ipcScanRelay(int argc, char *argv[]) { }
+void ipcInit(int argc, char *argv[]) { }
+
+#else
+
+static void ipcThread2(void* pArg);
+
+static bool ipcScanCmd(int argc, char *argv[], bool fRelay)
{
- message_queue::remove(BITCOINURI_QUEUE_NAME);
+ // Check for URI in argv
+ bool fSent = false;
+ for (int i = 1; i < argc; i++)
+ {
+ if (boost::algorithm::istarts_with(argv[i], "novacoin:"))
+ {
+ const char *strURI = argv[i];
+ try {
+ boost::interprocess::message_queue mq(boost::interprocess::open_only, BITCOINURI_QUEUE_NAME);
+ if (mq.try_send(strURI, strlen(strURI), 0))
+ fSent = true;
+ else if (fRelay)
+ break;
+ }
+ catch (boost::interprocess::interprocess_exception &ex) {
+ // don't log the "file not found" exception, because that's normal for
+ // the first start of the first instance
+ if (ex.get_error_code() != boost::interprocess::not_found_error || !fRelay)
+ {
+ printf("main() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what());
+ break;
+ }
+ }
+ }
+ }
+ return fSent;
}
-void ipcThread(void* parg)
+void ipcScanRelay(int argc, char *argv[])
{
- message_queue* mq = (message_queue*)parg;
- char strBuf[257];
- size_t nSize;
- unsigned int nPriority;
- loop
+ if (ipcScanCmd(argc, argv, true))
+ exit(0);
+}
+
+static void ipcThread(void* pArg)
+{
+ // Make this thread recognisable as the GUI-IPC thread
+ RenameThread("novacoin-gui-ipc");
+
+ try
+ {
+ ipcThread2(pArg);
+ }
+ catch (std::exception& e) {
+ PrintExceptionContinue(&e, "ipcThread()");
+ } catch (...) {
+ PrintExceptionContinue(NULL, "ipcThread()");
+ }
+ printf("ipcThread exited\n");
+}
+
+static void ipcThread2(void* pArg)
+{
+ printf("ipcThread started\n");
+
+ message_queue* mq = (message_queue*)pArg;
+ char buffer[MAX_URI_LENGTH + 1] = "";
+ size_t nSize = 0;
+ unsigned int nPriority = 0;
+
+ while (true)
{
ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(100);
- if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
+ if (mq->timed_receive(&buffer, sizeof(buffer), nSize, nPriority, d))
{
- ThreadSafeHandleURI(std::string(strBuf, nSize));
+ uiInterface.ThreadSafeHandleURI(std::string(buffer, nSize));
Sleep(1000);
}
+
if (fShutdown)
- {
- ipcShutdown();
break;
- }
}
- ipcShutdown();
+
+ // Remove message queue
+ message_queue::remove(BITCOINURI_QUEUE_NAME);
+ // Cleanup allocated memory
+ delete mq;
}
-void ipcInit()
+void ipcInit(int argc, char *argv[])
{
-#ifdef MAC_OSX
- // TODO: implement bitcoin: URI handling the Mac Way
- return;
-#endif
-#ifdef WIN32
- // TODO: THOROUGHLY test boost::interprocess fix,
- // and make sure there are no Windows argument-handling exploitable
- // problems.
- return;
-#endif
+ message_queue* mq = NULL;
+ char buffer[MAX_URI_LENGTH + 1] = "";
+ size_t nSize = 0;
+ unsigned int nPriority = 0;
- message_queue* mq;
- char strBuf[257];
- size_t nSize;
- unsigned int nPriority;
try {
- mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256);
+ mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, MAX_URI_LENGTH);
// Make sure we don't lose any bitcoin: URIs
for (int i = 0; i < 2; i++)
{
ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1);
- if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
+ if (mq->timed_receive(&buffer, sizeof(buffer), nSize, nPriority, d))
{
- ThreadSafeHandleURI(std::string(strBuf, nSize));
+ uiInterface.ThreadSafeHandleURI(std::string(buffer, nSize));
}
else
break;
// Make sure only one bitcoin instance is listening
message_queue::remove(BITCOINURI_QUEUE_NAME);
- mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, 256);
+ delete mq;
+
+ mq = new message_queue(open_or_create, BITCOINURI_QUEUE_NAME, 2, MAX_URI_LENGTH);
}
catch (interprocess_exception &ex) {
+ printf("ipcInit() - boost interprocess exception #%d: %s\n", ex.get_error_code(), ex.what());
return;
}
- if (!CreateThread(ipcThread, mq))
+
+ if (!NewThread(ipcThread, mq))
{
delete mq;
+ return;
}
+
+ ipcScanCmd(argc, argv, false);
}
+
+#endif