diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 55a587cf87dc9..a847d09acc361 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -98,7 +98,6 @@ BITCOIN_TESTS =\ test/hash_tests.cpp \ test/key_tests.cpp \ test/limitedmap_tests.cpp \ - test/dbwrapper_tests.cpp \ test/main_tests.cpp \ test/mempool_tests.cpp \ test/merkle_tests.cpp \ @@ -137,6 +136,10 @@ BITCOIN_TESTS =\ test/univalue_tests.cpp \ test/util_tests.cpp +# Disabled, need to figure out how to pass temporary directory +# to test first +# test/dbwrapper_tests.cpp \ +# if ENABLE_WALLET BITCOIN_TESTS += \ wallet/test/wallet_test_fixture.cpp \ diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp index b0df3d2b04dc6..ff9a7faf2181d 100644 --- a/src/bench/bench.cpp +++ b/src/bench/bench.cpp @@ -29,8 +29,10 @@ void benchmark::BenchRunner::RunAll(double elapsedTimeForOne) { perf_init(); +#ifndef CLOUDABI std::cout << "#Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << "," << "min_cycles" << "," << "max_cycles" << "," << "average_cycles" << "\n"; +#endif for (const auto &p: benchmarks()) { State state(p.first, elapsedTimeForOne); @@ -97,8 +99,10 @@ bool benchmark::State::KeepRunning() // Output results double average = (now-beginTime)/count; int64_t averageCycles = (nowCycles-beginCycles)/count; +#ifndef CLOUDABI std::cout << std::fixed << std::setprecision(15) << name << "," << count << "," << minTime << "," << maxTime << "," << average << "," << minCycles << "," << maxCycles << "," << averageCycles << "\n"; +#endif return false; } diff --git a/src/bench/rollingbloom.cpp b/src/bench/rollingbloom.cpp index 73c02cf7189eb..15f970d8d3d07 100644 --- a/src/bench/rollingbloom.cpp +++ b/src/bench/rollingbloom.cpp @@ -26,7 +26,9 @@ static void RollingBloom(benchmark::State& state) int64_t b = GetTimeMicros(); filter.insert(data); int64_t e = GetTimeMicros(); +#ifndef CLOUDABI std::cout << "RollingBloom-refresh,1," << (e-b)*0.000001 << "," << (e-b)*0.000001 << "," << (e-b)*0.000001 << "\n"; +#endif countnow = 0; } else { filter.insert(data); diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 31680a8ec765c..670fc160bdecb 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -24,6 +24,11 @@ #include #include +#ifdef CLOUDABI +#include +#include +#include +#endif /* Introduction text for doxygen: */ @@ -61,19 +66,13 @@ void WaitForShutdown(boost::thread_group* threadGroup) // // Start // -bool AppInit(int argc, char* argv[]) +bool AppInit() { boost::thread_group threadGroup; CScheduler scheduler; bool fRet = false; - // - // Parameters - // - // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main() - ParseParameters(argc, argv); - // Process help and version before taking care about datadir if (IsArgSet("-?") || IsArgSet("-h") || IsArgSet("-help") || IsArgSet("-version")) { @@ -91,7 +90,9 @@ bool AppInit(int argc, char* argv[]) strUsage += "\n" + HelpMessage(HMM_BITCOIND); } +#ifndef CLOUDABI fprintf(stdout, "%s", strUsage.c_str()); +#endif return true; } @@ -117,17 +118,6 @@ bool AppInit(int argc, char* argv[]) return false; } - // Command-line RPC - bool fCommandLine = false; - for (int i = 1; i < argc; i++) - if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "bitcoin:")) - fCommandLine = true; - - if (fCommandLine) - { - fprintf(stderr, "Error: There is no RPC client functionality in bitcoind anymore. Use the bitcoin-cli utility instead.\n"); - exit(EXIT_FAILURE); - } // -server defaults to true for bitcoind but not for the GUI so do this here SoftSetBoolArg("-server", true); // Set this early so that parameter interactions go to console @@ -186,6 +176,7 @@ bool AppInit(int argc, char* argv[]) return fRet; } +#ifndef CLOUDABI int main(int argc, char* argv[]) { SetupEnvironment(); @@ -193,5 +184,102 @@ int main(int argc, char* argv[]) // Connect bitcoind signal handlers noui_connect(); - return (AppInit(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE); + ParseParameters(argc, argv); + + return (AppInit() ? EXIT_SUCCESS : EXIT_FAILURE); +} +#else +void program_main(const argdata_t *ad) { + mstd::optional console_fd; + mstd::optional datadir_fd; + mstd::optional rpc_fd; + mstd::optional p2p_fd; + mstd::optional zmq_fd; + argdata_t::map args; + for (auto &i: ad->as_map()) { + auto key = i.first->as_str(); + if (key == "console") { + console_fd = i.second->get_fd(); + } else if(key == "datadir") { + datadir_fd = i.second->get_fd(); + } else if(key == "args") { + args = i.second->as_map(); + } else if(key == "rpc") { + rpc_fd = i.second->get_fd(); + } else if(key == "p2p") { + p2p_fd = i.second->get_fd(); + } else if(key == "zmq") { + zmq_fd = i.second->get_fd(); + } + } + // Console fd is optional + if (console_fd) { + SetConsoleFD(console_fd.value()); + } + // Datadir fd is mandatory + if (datadir_fd) { + SetDataDirFD(datadir_fd.value()); + } else { + LogPrintf("Need to specify data directory\n"); + std::exit(1); + } + // Log test message + fPrintToConsole = true; + LogPrintf("Welcome to cloudabi\n"); + + SetupEnvironment(); + noui_connect(); + + // Process arguments + LogPrintf("Processing arguments\n"); + for (const auto &entry: args) { + std::string key = "-" + std::string(entry.first->as_str()); + mstd::optional seqval = entry.second->get_seq(); + if (seqval) { + std::vector values; + for (const auto &x: seqval.value()) { + values.push_back(std::string(x->as_str())); + } + LogPrintf("multiarg %s: %s\n", key, boost::algorithm::join(values, ", ")); + SoftSetMultiArg(key, values); + } else { /* Convert any sensible kind of argument to string */ + mstd::optional strval = entry.second->get_str(); + mstd::optional boolval = entry.second->get_bool(); + mstd::optional doubleval = entry.second->get_float(); + mstd::optional intval = entry.second->get_int(); + std::string value; + if (strval) { + value = strval.value(); + } else if (boolval) { + value = boolval.value() ? "1" : "0"; + } else if(doubleval) { + value = strprintf("%f", doubleval.value()); + } else if(intval) { + value = strprintf("%d", intval.value()); + } + LogPrintf("arg %s: %s\n", key, value); + SoftSetArg(key, value); + } + } + // Pass RPC and P2P fd as arguments + // TODO: should be able to accept mulitple of these to bind to multiple addresses, + // as well as associated bind/whitelist flags. + // TODO: this is a hack, these arguments should be passed in a configuration + // structure instead of magically enter the program through a global + // namespace. + if (rpc_fd) { + ForceSetArg("-rpcfd", itostr(rpc_fd.value())); + LogPrintf("rpcfd: %i\n", rpc_fd.value()); + } + if (p2p_fd) { + ForceSetArg("-p2pfd", itostr(p2p_fd.value())); + LogPrintf("p2pfd: %i\n", p2p_fd.value()); + } + if (zmq_fd) { + ForceSetArg("-zmqfd", itostr(zmq_fd.value())); + LogPrintf("zmqfd: %i\n", zmq_fd.value()); + } + + std::exit(AppInit() ? EXIT_SUCCESS : EXIT_FAILURE); } +#endif diff --git a/src/compat.h b/src/compat.h index e76ab94c82bc1..a2ea35015e4fb 100644 --- a/src/compat.h +++ b/src/compat.h @@ -32,16 +32,22 @@ #include #include #else +#ifndef CLOUDABI #include +#endif #include #include #include #include #include #include +#ifndef CLOUDABI #include +#endif #include +#ifndef CLOUDABI #include +#endif #include #include #include @@ -84,4 +90,9 @@ bool static inline IsSelectableSocket(SOCKET s) { #endif } +#ifdef CLOUDABI +/* Define some constants that are not available on cloudabi */ +#define INADDR_NONE ((unsigned long int) 0xffffffff) +#endif + #endif // BITCOIN_COMPAT_H diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index a373b9324b107..317ee6d9cc2f3 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include static leveldb::Options GetOptions(size_t nCacheSize) @@ -32,16 +32,15 @@ static leveldb::Options GetOptions(size_t nCacheSize) CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate) { - penv = NULL; readoptions.verify_checksums = true; iteroptions.verify_checksums = true; iteroptions.fill_cache = false; syncoptions.sync = true; options = GetOptions(nCacheSize); options.create_if_missing = true; + penv = leveldb::Env::DefaultWithDirectory(path.fd()); if (fMemory) { - penv = leveldb::NewMemEnv(leveldb::Env::Default()); - options.env = penv; + penv = leveldb::NewMemEnv(penv); } else { if (fWipe) { LogPrintf("Wiping LevelDB in %s\n", path.string()); @@ -51,6 +50,7 @@ CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bo TryCreateDirectory(path); LogPrintf("Opening LevelDB in %s\n", path.string()); } + options.env = penv; leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb); dbwrapper_private::HandleError(status); LogPrintf("Opened LevelDB successfully\n"); diff --git a/src/httpserver.cpp b/src/httpserver.cpp index e1763c6ad276c..6ba0042e6ab21 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -318,6 +319,7 @@ static bool ThreadHTTP(struct event_base* base, struct evhttp* http) /** Bind HTTP server to specified addresses */ static bool HTTPBindAddresses(struct evhttp* http) { +#ifndef CLOUDABI int defaultPort = GetArg("-rpcport", BaseParams().RPCPort()); std::vector > endpoints; @@ -351,6 +353,21 @@ static bool HTTPBindAddresses(struct evhttp* http) LogPrintf("Binding RPC on address %s port %i failed.\n", i->first, i->second); } } +#else + int fd = GetArg("-rpcfd", -1); + if (fd >= 0) { + LogPrintf("Binding RPC on fd %d.\n", fd); + /* Need to explicitly set the socket to non-blocking */ + evutil_make_socket_nonblocking(fd); + + evhttp_bound_socket *bind_handle = evhttp_accept_socket_with_handle(http, fd); + if (bind_handle) { + boundSockets.push_back(bind_handle); + } else { + LogPrintf("Binding RPC on fd %d failed.\n", fd); + } + } +#endif return !boundSockets.empty(); } diff --git a/src/init.cpp b/src/init.cpp index 4cc1e5ce0fcd6..1555cd4583f1c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -57,7 +57,9 @@ #include #include #include +#ifndef CLOUDABI #include +#endif #include #include @@ -247,7 +249,7 @@ void Shutdown() } #endif -#ifndef WIN32 +#if !defined(WIN32) and !defined(CLOUDABI) try { fs::remove(GetPidFile()); } catch (const fs::filesystem_error& e) { @@ -277,6 +279,7 @@ void HandleSIGHUP(int) fReopenDebugLog = true; } +#ifndef CLOUDABI bool static Bind(CConnman& connman, const CService &addr, unsigned int flags) { if (!(flags & BF_EXPLICIT) && IsLimited(addr)) return false; @@ -288,6 +291,8 @@ bool static Bind(CConnman& connman, const CService &addr, unsigned int flags) { } return true; } +#endif + void OnRPCStarted() { uiInterface.NotifyBlockTip.connect(&RPCNotifyBlockChange); @@ -577,6 +582,7 @@ void CleanupBlockRevFiles() // ordered map keyed by block file index. LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n"); fs::path blocksdir = GetDataDir() / "blocks"; +#ifndef CLOUDABI for (fs::directory_iterator it(blocksdir); it != fs::directory_iterator(); it++) { if (is_regular_file(*it) && it->path().filename().string().length() == 12 && @@ -588,6 +594,7 @@ void CleanupBlockRevFiles() remove(it->path()); } } +#endif // Remove all block files that aren't part of a contiguous set starting at // zero by walking the ordered map (keys are block file indices) by @@ -845,7 +852,7 @@ bool AppInitBasicSetup() if (!SetupNetworking()) return InitError("Initializing networking failed"); -#ifndef WIN32 +#if !defined(WIN32) and !defined(CLOUDABI) if (!GetBoolArg("-sysperms", false)) { umask(077); } @@ -1112,6 +1119,7 @@ bool AppInitParameterInteraction() static bool LockDataDirectory(bool probeOnly) { +#ifndef CLOUDABI std::string strDataDir = GetDataDir().string(); // Make sure only a single Bitcoin process is using the data directory. @@ -1130,6 +1138,7 @@ static bool LockDataDirectory(bool probeOnly) } catch(const boost::interprocess::interprocess_exception& e) { return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running.") + " %s.", strDataDir, _(PACKAGE_NAME), e.what())); } +#endif return true; } @@ -1161,7 +1170,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) return false; } -#ifndef WIN32 +#if !defined(WIN32) && !defined(CLOUDABI) CreatePidFile(GetPidFile(), getpid()); #endif if (GetBoolArg("-shrinkdebugfile", !fDebug)) { @@ -1318,6 +1327,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) if (fListen) { bool fBound = false; +#ifndef CLOUDABI if (mapMultiArgs.count("-bind")) { BOOST_FOREACH(const std::string& strBind, mapMultiArgs.at("-bind")) { CService addrBind; @@ -1342,6 +1352,19 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) fBound |= Bind(connman, CService(in6addr_any, GetListenPort()), BF_NONE); fBound |= Bind(connman, CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE); } +#else + if (IsArgSet("-p2pfd")) { + std::string strError; + int fd = GetArg("-p2pfd", -1); + // TODO: whitebind + if (!connman.BindListenFD(fd, strError, false)) { + return InitError(strError); + } + fBound = true; + } else { + LogPrintf("Warning: No RPC fd provided\n"); + } +#endif if (!fBound) return InitError(_("Failed to listen on any port. Use -listen=0 if you want this.")); } diff --git a/src/net.cpp b/src/net.cpp index d8e86af3937c9..fe6c602c3611a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1066,7 +1066,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { CloseSocket(hSocket); return; } - +#ifdef TCP_NODELAY // According to the internet TCP_NODELAY is not carried into accepted sockets // on all platforms. Set it again here just to be sure. int set = 1; @@ -1074,6 +1074,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int)); #else setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&set, sizeof(int)); +#endif #endif if (IsBanned(addr) && !whitelisted) @@ -1999,6 +2000,7 @@ void CConnman::ThreadMessageHandler() +#ifndef CLOUDABI bool CConnman::BindListenPort(const CService &addrBind, std::string& strError, bool fWhitelisted) { strError = ""; @@ -2034,11 +2036,15 @@ bool CConnman::BindListenPort(const CService &addrBind, std::string& strError, b // Different way of disabling SIGPIPE on BSD setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int)); #endif +#ifdef SO_REUSEADDR // Allow binding if the port is still in TIME_WAIT state after // the program was closed and restarted. setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int)); +#endif +#ifdef TCP_NODELAY // Disable Nagle's algorithm setsockopt(hListenSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&nOne, sizeof(int)); +#endif #else setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&nOne, sizeof(int)); setsockopt(hListenSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&nOne, sizeof(int)); @@ -2066,7 +2072,6 @@ bool CConnman::BindListenPort(const CService &addrBind, std::string& strError, b setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int)); #endif } - if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) { int nErr = WSAGetLastError(); @@ -2096,6 +2101,15 @@ bool CConnman::BindListenPort(const CService &addrBind, std::string& strError, b return true; } +#endif + +bool CConnman::BindListenFD(SOCKET hListenSocket, std::string& strError, bool fWhitelisted) +{ + LogPrintf("Listening on fd %d\n", hListenSocket); + + vhListenSocket.push_back(ListenSocket(hListenSocket, fWhitelisted)); + return true; +} void Discover(boost::thread_group& threadGroup) { @@ -2117,7 +2131,7 @@ void Discover(boost::thread_group& threadGroup) } } } -#else +#elif !defined(CLOUDABI) // Get local host ip struct ifaddrs* myaddrs; if (getifaddrs(&myaddrs) == 0) diff --git a/src/net.h b/src/net.h index 6b938561f6d43..4ff3a34d95ca9 100644 --- a/src/net.h +++ b/src/net.h @@ -151,7 +151,11 @@ class CConnman bool Start(CScheduler& scheduler, std::string& strNodeError, Options options); void Stop(); void Interrupt(); +#ifndef CLOUDABI bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); +#endif + /** Listen directly on a socket, provided as file descriptor */ + bool BindListenFD(SOCKET hListenSocket, std::string& strError, bool fWhitelisted = false); bool GetNetworkActive() const { return fNetworkActive; }; void SetNetworkActive(bool active); bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false, bool fAddnode = false); diff --git a/src/netbase.cpp b/src/netbase.cpp index 0f02e93e46ae8..ca27b0db60cbd 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -89,6 +89,7 @@ bool static LookupIntern(const char *pszName, std::vector& vIP, unsign } } +#ifndef CLOUDABI struct addrinfo aiHint; memset(&aiHint, 0, sizeof(struct addrinfo)); @@ -125,7 +126,17 @@ bool static LookupIntern(const char *pszName, std::vector& vIP, unsign } freeaddrinfo(aiRes); +#else /* no name lookup, attempt parsing IP4/6 with inet_pton */ + struct in_addr ipv4_addr; + if (inet_pton(AF_INET, pszName, &ipv4_addr) > 0) { + vIP.push_back(CNetAddr(ipv4_addr)); + } + struct in6_addr ipv6_addr; + if (inet_pton(AF_INET6, pszName, &ipv6_addr) > 0) { + vIP.push_back(CNetAddr(ipv6_addr)); + } +#endif return (vIP.size() > 0); } @@ -415,6 +426,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout) { +#ifndef CLOUDABI hSocketRet = INVALID_SOCKET; struct sockaddr_storage sockaddr; @@ -500,6 +512,9 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe hSocketRet = hSocket; return true; +#else + return false; +#endif } bool SetProxy(enum Network net, const proxyType &addrProxy) { diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index 2cb3003b0d45f..a5b54cb61e8bf 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -77,6 +77,7 @@ fs::path GetAuthCookieFile() bool GenerateAuthCookie(std::string *cookie_out) { +#ifndef CLOUDABI const size_t COOKIE_SIZE = 32; unsigned char rand_pwd[COOKIE_SIZE]; GetRandBytes(rand_pwd, COOKIE_SIZE); @@ -99,10 +100,14 @@ bool GenerateAuthCookie(std::string *cookie_out) if (cookie_out) *cookie_out = cookie; return true; +#else + return false; +#endif } bool GetAuthCookie(std::string *cookie_out) { +#ifndef CLOUDABI std::ifstream file; std::string cookie; fs::path filepath = GetAuthCookieFile(); @@ -115,14 +120,19 @@ bool GetAuthCookie(std::string *cookie_out) if (cookie_out) *cookie_out = cookie; return true; +#else + return false; +#endif } void DeleteAuthCookie() { +#ifndef CLOUDABI try { fs::remove(GetAuthCookieFile()); } catch (const fs::filesystem_error& e) { LogPrintf("%s: Unable to remove random auth cookie file: %s\n", __func__, e.what()); } +#endif } diff --git a/src/support/lockedpool.cpp b/src/support/lockedpool.cpp index 98c15810934dc..6ded7fb92be46 100644 --- a/src/support/lockedpool.cpp +++ b/src/support/lockedpool.cpp @@ -228,16 +228,22 @@ void *PosixLockedPageAllocator::AllocateLocked(size_t len, bool *lockingSuccess) void *addr; len = align_up(len, page_size); addr = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); +#ifndef CLOUDABI if (addr) { *lockingSuccess = mlock(addr, len) == 0; } +#else /* Need to find another way to get locked memory to the process */ + *lockingSuccess = false; +#endif return addr; } void PosixLockedPageAllocator::FreeLocked(void* addr, size_t len) { len = align_up(len, page_size); memory_cleanse(addr, len); +#ifndef CLOUDABI munlock(addr, len); +#endif munmap(addr, len); } size_t PosixLockedPageAllocator::GetLimit() diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 5279cb243bafc..a069a9f3c9566 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -30,7 +30,9 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); if (nIn >= txTo.vin.size()) { +#if 0 printf("ERROR: SignatureHash(): nIn=%d out of range\n", nIn); +#endif return one; } CMutableTransaction txTmp(txTo); @@ -61,7 +63,9 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un unsigned int nOut = nIn; if (nOut >= txTmp.vout.size()) { +#if 0 printf("ERROR: SignatureHash(): nOut=%d out of range\n", nOut); +#endif return one; } txTmp.vout.resize(nOut+1); diff --git a/src/test/test_bitcoin_fuzzy.cpp b/src/test/test_bitcoin_fuzzy.cpp index c4983f6f5ccdf..869c0e203ec2e 100644 --- a/src/test/test_bitcoin_fuzzy.cpp +++ b/src/test/test_bitcoin_fuzzy.cpp @@ -49,6 +49,7 @@ enum TEST_ID { }; bool read_stdin(std::vector &data) { +#ifndef CLOUDABI char buffer[1024]; ssize_t length=0; while((length = read(STDIN_FILENO, buffer, 1024)) > 0) { @@ -57,6 +58,9 @@ bool read_stdin(std::vector &data) { if (data.size() > (1<<20)) return false; } return length==0; +#else + return false; +#endif } int main(int argc, char **argv) diff --git a/src/test/testutil.cpp b/src/test/testutil.cpp index 591d0bf302712..fbe2eaef5b6fa 100644 --- a/src/test/testutil.cpp +++ b/src/test/testutil.cpp @@ -11,5 +11,9 @@ #include "fs.h" fs::path GetTempPath() { +#ifdef CLOUDABI + return fs::path("."); +#else return fs::temp_directory_path(); +#endif } diff --git a/src/tinyformat.h b/src/tinyformat.h index 17f0360c42f24..b794d24cd0de1 100644 --- a/src/tinyformat.h +++ b/src/tinyformat.h @@ -960,6 +960,7 @@ std::string format(const char* fmt, const Args&... args) return oss.str(); } +#ifndef CLOUDABI /// Format list of arguments to std::cout, according to the given format string template void printf(const char* fmt, const Args&... args) @@ -973,6 +974,7 @@ void printfln(const char* fmt, const Args&... args) format(std::cout, fmt, args...); std::cout << '\n'; } +#endif #else // C++98 version diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 5a5aa6007557c..ffe78274b6256 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -215,13 +215,16 @@ bool TorControlConnection::Connect(const std::string &target, const ConnectionCB bufferevent_enable(b_conn, EV_READ|EV_WRITE); this->connected = _connected; this->disconnected = _disconnected; - +#ifndef CLOUDABI // Finally, connect to target if (bufferevent_socket_connect(b_conn, (struct sockaddr*)&connect_to_addr, connect_to_addrlen) < 0) { LogPrintf("tor: Error connecting to address %s\n", target); return false; } return true; +#else + return false; +#endif } bool TorControlConnection::Disconnect() diff --git a/src/util.cpp b/src/util.cpp index 7872fc3a7814a..8c7c74ad197af 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -115,6 +115,13 @@ bool fLogIPs = DEFAULT_LOGIPS; std::atomic fReopenDebugLog(false); CTranslationInterface translationInterface; +int dataDirFD = -1; +#ifndef CLOUDABI +FILE *consout = stdout; +#else +FILE *consout; +#endif + /** Init OpenSSL library multithreading support */ static CCriticalSection** ppmutexOpenSSL; void locking_callback(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS @@ -297,8 +304,11 @@ int LogPrintStr(const std::string &str) if (fPrintToConsole) { // print to console - ret = fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout); - fflush(stdout); + if (consout) + { + ret = fwrite(strTimestamped.data(), 1, strTimestamped.size(), consout); + fflush(consout); + } } else if (fPrintToDebugLog) { @@ -428,6 +438,16 @@ bool SoftSetBoolArg(const std::string& strArg, bool fValue) return SoftSetArg(strArg, std::string("0")); } +bool SoftSetMultiArg(const std::string& strArg, const std::vector& values) +{ + LOCK(cs_args); + if (_mapMultiArgs.count(strArg)) + return false; + _mapMultiArgs[strArg] = values; + return true; +} + + void ForceSetArg(const std::string& strArg, const std::string& strValue) { LOCK(cs_args); @@ -483,6 +503,8 @@ fs::path GetDefaultDataDir() #ifdef WIN32 // Windows return GetSpecialFolderPath(CSIDL_APPDATA) / "Bitcoin"; +#elif defined(CLOUDABI) + return fs::path(dataDirFD, "."); #else fs::path pathRet; char* pszHome = getenv("HOME"); @@ -517,7 +539,11 @@ const fs::path &GetDataDir(bool fNetSpecific) return path; if (IsArgSet("-datadir")) { +#ifndef CLOUDABI path = fs::system_complete(GetArg("-datadir", "")); +#else + path = fs::path(dataDirFD, GetArg("-datadir", "")); +#endif if (!fs::is_directory(path)) { path = ""; return path; @@ -533,6 +559,21 @@ const fs::path &GetDataDir(bool fNetSpecific) return path; } +int GetDataDirFD() +{ + return dataDirFD; +} + +void SetDataDirFD(int fd) +{ + dataDirFD = fd; +} + +void SetConsoleFD(int fd) +{ + consout = fdopen(fd, "w"); +} + void ClearDatadirCache() { LOCK(csPathCached); @@ -552,6 +593,7 @@ fs::path GetConfigFile(const std::string& confPath) void ReadConfigFile(const std::string& confPath) { +#ifndef CLOUDABI fs::ifstream streamConfig(GetConfigFile(confPath)); if (!streamConfig.good()) return; // No bitcoin.conf file is OK @@ -574,9 +616,10 @@ void ReadConfigFile(const std::string& confPath) } // If datadir is changed in .conf file: ClearDatadirCache(); +#endif } -#ifndef WIN32 +#if !defined(WIN32) && !defined(CLOUDABI) fs::path GetPidFile() { fs::path pathPidFile(GetArg("-pid", BITCOIN_PID_FILENAME)); @@ -600,6 +643,13 @@ bool RenameOver(fs::path src, fs::path dest) #ifdef WIN32 return MoveFileExA(src.string().c_str(), dest.string().c_str(), MOVEFILE_REPLACE_EXISTING) != 0; +#elif defined(CLOUDABI) + try { + fs::rename(src, dest); + return true; + } catch (const fs::filesystem_error &) { + return false; + } #else int rc = std::rename(src.string().c_str(), dest.string().c_str()); return (rc == 0); @@ -657,6 +707,8 @@ bool TruncateFile(FILE *file, unsigned int length) { int RaiseFileDescriptorLimit(int nMinFD) { #if defined(WIN32) return 2048; +#elif defined(CLOUDABI) + return 2048; /* ??? */ #else struct rlimit limitFD; if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) { @@ -764,9 +816,11 @@ fs::path GetSpecialFolderPath(int nFolder, bool fCreate) void runCommand(const std::string& strCommand) { +#ifndef CLOUDABI int nErr = ::system(strCommand.c_str()); if (nErr) LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr); +#endif } void RenameThread(const char* name) @@ -787,6 +841,7 @@ void RenameThread(const char* name) void SetupEnvironment() { +#ifndef CLOUDABI // On most POSIX systems (e.g. Linux, but not BSD) the environment's locale // may be invalid, in which case the "C" locale is used as fallback. #if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__) @@ -802,6 +857,7 @@ void SetupEnvironment() // fs::path, which is then used to explicitly imbue the path. std::locale loc = fs::path::imbue(std::locale::classic()); fs::path::imbue(loc); +#endif } bool SetupNetworking() diff --git a/src/util.h b/src/util.h index 786717fbb6a07..f814268a7a045 100644 --- a/src/util.h +++ b/src/util.h @@ -100,9 +100,17 @@ bool RenameOver(fs::path src, fs::path dest); bool TryCreateDirectory(const fs::path& p); fs::path GetDefaultDataDir(); const fs::path &GetDataDir(bool fNetSpecific = true); + +#ifdef CLOUDABI +/** Set fd under to which the data directory is relative */ +void SetDataDirFD(int fd); +/** Set console fd */ +void SetConsoleFD(int fd); +#endif + void ClearDatadirCache(); fs::path GetConfigFile(const std::string& confPath); -#ifndef WIN32 +#if !defined(WIN32) and !defined(CLOUDABI) fs::path GetPidFile(); void CreatePidFile(const fs::path &path, pid_t pid); #endif @@ -167,6 +175,15 @@ bool GetBoolArg(const std::string& strArg, bool fDefault); */ bool SoftSetArg(const std::string& strArg, const std::string& strValue); +/** + * Set a multi-argument if it doesn't already have a value + * + * @param strArg Argument to set (e.g. "-foo") + * @param strValues Values (e.g. {"1","2"}) + * @return true if argument gets set, false if it already had a value + */ +bool SoftSetMultiArg(const std::string& strArg, const std::vector& values); + /** * Set a boolean argument if it doesn't already have a value * diff --git a/src/zmq/zmqabstractnotifier.h b/src/zmq/zmqabstractnotifier.h index 77cf5141e27b7..c8360413d22d9 100644 --- a/src/zmq/zmqabstractnotifier.h +++ b/src/zmq/zmqabstractnotifier.h @@ -29,7 +29,7 @@ class CZMQAbstractNotifier std::string GetAddress() const { return address; } void SetAddress(const std::string &a) { address = a; } - virtual bool Initialize(void *pcontext) = 0; + virtual bool Initialize(void *pcontext, int fd) = 0; virtual void Shutdown() = 0; virtual bool NotifyBlock(const CBlockIndex *pindex); diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 431d8c9ac952d..8e2ca8a37fc9b 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -34,6 +34,7 @@ CZMQNotificationInterface* CZMQNotificationInterface::Create() CZMQNotificationInterface* notificationInterface = NULL; std::map factories; std::list notifiers; + int fd = GetArg("-zmqfd", -1); factories["pubhashblock"] = CZMQAbstractNotifier::Create; factories["pubhashtx"] = CZMQAbstractNotifier::Create; @@ -59,7 +60,7 @@ CZMQNotificationInterface* CZMQNotificationInterface::Create() notificationInterface = new CZMQNotificationInterface(); notificationInterface->notifiers = notifiers; - if (!notificationInterface->Initialize()) + if (!notificationInterface->Initialize(fd)) { delete notificationInterface; notificationInterface = NULL; @@ -70,7 +71,7 @@ CZMQNotificationInterface* CZMQNotificationInterface::Create() } // Called at startup to conditionally set up ZMQ socket(s) -bool CZMQNotificationInterface::Initialize() +bool CZMQNotificationInterface::Initialize(int fd) { LogPrint("zmq", "zmq: Initialize notification interface\n"); assert(!pcontext); @@ -87,7 +88,7 @@ bool CZMQNotificationInterface::Initialize() for (; i!=notifiers.end(); ++i) { CZMQAbstractNotifier *notifier = *i; - if (notifier->Initialize(pcontext)) + if (notifier->Initialize(pcontext, fd)) { LogPrint("zmq", " Notifier %s ready (address = %s)\n", notifier->GetType(), notifier->GetAddress()); } diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index beabb78da6d3d..a9cdff264b15c 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -20,7 +20,7 @@ class CZMQNotificationInterface : public CValidationInterface static CZMQNotificationInterface* Create(); protected: - bool Initialize(); + bool Initialize(int fd); void Shutdown(); // CValidationInterface diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index caca1248a1ad9..5c557487b1576 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -56,7 +56,7 @@ static int zmq_send_multipart(void *sock, const void* data, size_t size, ...) return 0; } -bool CZMQAbstractPublishNotifier::Initialize(void *pcontext) +bool CZMQAbstractPublishNotifier::Initialize(void *pcontext, int fd) { assert(!psocket); @@ -72,7 +72,15 @@ bool CZMQAbstractPublishNotifier::Initialize(void *pcontext) return false; } - int rc = zmq_bind(psocket, address.c_str()); + int rc = zmq_setsockopt(psocket, ZMQ_USE_FD, &fd, sizeof(fd)); + if (rc!=0) + { + zmqError("Failed to set FD"); + zmq_close(psocket); + return false; + } + + rc = zmq_bind(psocket, address.c_str()); if (rc!=0) { zmqError("Failed to bind address"); diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h index bcbecf1bde13b..a3e9ab342356e 100644 --- a/src/zmq/zmqpublishnotifier.h +++ b/src/zmq/zmqpublishnotifier.h @@ -24,7 +24,7 @@ class CZMQAbstractPublishNotifier : public CZMQAbstractNotifier */ bool SendMessage(const char *command, const void* data, size_t size); - bool Initialize(void *pcontext); + bool Initialize(void *pcontext, int fd); void Shutdown(); };