// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#include "headers.h"
#include "db.h"
-#include "rpc.h"
+#include "bitcoinrpc.h"
#include "net.h"
#include "init.h"
#include "strlcpy.h"
#include <boost/filesystem/fstream.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
+#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
+#define _BITCOIN_QT_PLUGINS_INCLUDED
+#define __INSURE__
+#include <QtPlugin>
+Q_IMPORT_PLUGIN(qcncodecs)
+Q_IMPORT_PLUGIN(qjpcodecs)
+Q_IMPORT_PLUGIN(qtwcodecs)
+Q_IMPORT_PLUGIN(qkrcodecs)
+#endif
+
using namespace std;
using namespace boost;
void ExitTimeout(void* parg)
{
-#ifdef __WXMSW__
+#ifdef WIN32
Sleep(5000);
ExitProcess(0);
#endif
//
// Start
//
-#ifndef GUI
+#if !defined(QT_GUI)
int main(int argc, char* argv[])
{
bool fRet = false;
// Disable confusing "helpful" text message on abort, ctrl-c
_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
#endif
-#ifndef __WXMSW__
+#ifndef WIN32
umask(077);
#endif
-#ifndef __WXMSW__
+#ifndef WIN32
// Clean shutdown on SIGTERM
struct sigaction sa;
sa.sa_handler = HandleSIGTERM;
" -maxconnections=<n>\t " + _("Maintain at most <n> connections to peers (default: 125)\n") +
" -addnode=<ip> \t " + _("Add a node to connect to\n") +
" -connect=<ip> \t\t " + _("Connect only to the specified node\n") +
+ " -noirc \t " + _("Don't find peers using internet relay chat\n") +
" -nolisten \t " + _("Don't accept connections from outside\n") +
" -nodnsseed \t " + _("Don't bootstrap list of peers using DNS\n") +
+ " -banscore=<n> \t " + _("Threshold for disconnecting misbehaving peers (default: 100)\n") +
+ " -bantime=<n> \t " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)\n") +
" -maxreceivebuffer=<n>\t " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)\n") +
" -maxsendbuffer=<n>\t " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)\n") +
#ifdef USE_UPNP
#ifdef GUI
" -server \t\t " + _("Accept command line and JSON-RPC commands\n") +
#endif
-#ifndef __WXMSW__
+#ifndef WIN32
" -daemon \t\t " + _("Run in the background as a daemon and accept commands\n") +
#endif
" -testnet \t\t " + _("Use the test network\n") +
strUsage += string() +
" -? \t\t " + _("This help message\n");
// Remove tabs
strUsage.erase(std::remove(strUsage.begin(), strUsage.end(), '\t'), strUsage.end());
fprintf(stderr, "%s", strUsage.c_str());
return false;
}
+ fTestNet = GetBoolArg("-testnet");
fDebug = GetBoolArg("-debug");
- fAllowDNS = GetBoolArg("-dns");
-#ifndef __WXMSW__
+#ifndef WIN32
fDaemon = GetBoolArg("-daemon");
#else
fDaemon = false;
fServer = GetBoolArg("-server");
/* force fServer when running without GUI */
-#ifndef GUI
+#if !defined(QT_GUI)
fServer = true;
#endif
-
fPrintToConsole = GetBoolArg("-printtoconsole");
fPrintToDebugger = GetBoolArg("-printtodebugger");
-
- fTestNet = GetBoolArg("-testnet");
- bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
- fNoListen = GetBoolArg("-nolisten") || fTOR;
fLogTimestamps = GetBoolArg("-logtimestamps");
+#ifndef QT_GUI
for (int i = 1; i < argc; i++)
if (!IsSwitchChar(argv[i][0]))
fCommandLine = true;
int ret = CommandLineRPC(argc, argv);
exit(ret);
}
+#endif
-#ifndef __WXMSW__
+#ifndef WIN32
if (fDaemon)
{
// Daemonize
ShrinkDebugFile();
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
printf("Bitcoin version %s\n", FormatFullVersion().c_str());
-#ifdef GUI
- printf("OS version %s\n", ((string)wxGetOsDescription()).c_str());
- printf("System default language is %d %s\n", g_locale.GetSystemLanguage(), ((string)g_locale.GetSysName()).c_str());
- printf("Language file %s (%s)\n", (string("locale/") + (string)g_locale.GetCanonicalName() + "/LC_MESSAGES/bitcoin.mo").c_str(), ((string)g_locale.GetLocale()).c_str());
-#endif
printf("Default data directory %s\n", GetDefaultDataDir().c_str());
if (GetBoolArg("-loadblockindextest"))
return false;
}
- //
- // Limit to single instance per user
- // Required to protect the database files if we're going to keep deleting log.*
- //
-#if defined(__WXMSW__) && defined(GUI)
- // wxSingleInstanceChecker doesn't work on Linux
- wxString strMutexName = wxString("bitcoin_running.") + getenv("HOMEPATH");
- for (int i = 0; i < strMutexName.size(); i++)
- if (!isalnum(strMutexName[i]))
- strMutexName[i] = '.';
- wxSingleInstanceChecker* psingleinstancechecker = new wxSingleInstanceChecker(strMutexName);
- if (psingleinstancechecker->IsAnotherRunning())
- {
- printf("Existing instance found\n");
- unsigned int nStart = GetTime();
- loop
- {
- // Show the previous instance and exit
- HWND hwndPrev = FindWindowA("wxWindowClassNR", "Bitcoin");
- if (hwndPrev)
- {
- if (IsIconic(hwndPrev))
- ShowWindow(hwndPrev, SW_RESTORE);
- SetForegroundWindow(hwndPrev);
- return false;
- }
-
- if (GetTime() > nStart + 60)
- return false;
-
- // Resume this instance if the other exits
- delete psingleinstancechecker;
- Sleep(1000);
- psingleinstancechecker = new wxSingleInstanceChecker(strMutexName);
- if (!psingleinstancechecker->IsAnotherRunning())
- break;
- }
- }
-#endif
-
// Make sure only a single bitcoin process is using the data directory.
string strLockFile = GetDataDir() + "/.lock";
FILE* file = fopen(strLockFile.c_str(), "a"); // empty lock file; created if it doesn't exist.
return false;
}
- // Bind to the port early so we can tell if another instance is already running.
string strErrors;
- if (!fNoListen)
- {
- if (!BindListenPort(strErrors))
- {
- wxMessageBox(strErrors, "Bitcoin");
- return false;
- }
- }
//
// Load data files
strErrors = "";
int64 nStart;
+ InitMessage(_("Loading addresses..."));
printf("Loading addresses...\n");
nStart = GetTimeMillis();
if (!LoadAddresses())
strErrors += _("Error loading addr.dat \n");
printf(" addresses %15"PRI64d"ms\n", GetTimeMillis() - nStart);
+ InitMessage(_("Loading block index..."));
printf("Loading block index...\n");
nStart = GetTimeMillis();
if (!LoadBlockIndex())
strErrors += _("Error loading blkindex.dat \n");
printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
+ InitMessage(_("Loading wallet..."));
printf("Loading wallet...\n");
nStart = GetTimeMillis();
bool fFirstRun;
}
if (pindexBest != pindexRescan)
{
+ InitMessage(_("Rescanning..."));
printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight);
nStart = GetTimeMillis();
pwalletMain->ScanForWalletTransactions(pindexRescan, true);
printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
}
+ InitMessage(_("Done loading"));
printf("Done loading\n");
//// debug print
// Add wallet transactions that aren't already in a block to mapTransactions
pwalletMain->ReacceptWalletTransactions();
+ // Note: Bitcoin-QT stores several settings in the wallet, so we want
+ // to load the wallet BEFORE parsing command-line arguments, so
+ // the command-line/bitcoin.conf settings override GUI setting.
+
//
// Parameters
//
}
}
+ bool fTor = (fUseProxy && addrProxy.port == htons(9050));
+ if (fTor)
+ {
+ // Use SoftSetArg here so user can override any of these if they wish.
+ // Note: the GetBoolArg() calls for all of these must happen later.
+ SoftSetArg("-nolisten", true);
+ SoftSetArg("-noirc", true);
+ SoftSetArg("-nodnsseed", true);
+ SoftSetArg("-noupnp", true);
+ SoftSetArg("-upnp", false);
+ SoftSetArg("-dns", false);
+ }
+
+ fAllowDNS = GetBoolArg("-dns");
+ fNoListen = GetBoolArg("-nolisten");
+
+ if (fHaveUPnP)
+ {
+ #if USE_UPNP
+ if (GetBoolArg("-noupnp"))
+ fUseUPnP = false;
+ #else
+ if (GetBoolArg("-upnp"))
+ fUseUPnP = true;
+ #endif
+ }
+
+ if (!fNoListen)
+ {
+ if (!BindListenPort(strErrors))
+ {
+ wxMessageBox(strErrors, "Bitcoin");
+ return false;
+ }
+ }
+
if (mapArgs.count("-addnode"))
{
BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin", wxOK | wxICON_EXCLAMATION);
}
- if (fHaveUPnP)
- {
- #if USE_UPNP
- if (GetBoolArg("-noupnp"))
- fUseUPnP = false;
- #else
- if (GetBoolArg("-upnp"))
- fUseUPnP = true;
- #endif
- }
-
//
- // Create the main window and start the node
+ // Start the node
//
-#ifdef GUI
- if (!fDaemon)
- CreateMainWindow();
-#endif
-
if (!CheckDiskSpace())
return false;
RandAddSeedPerfmon();
if (!CreateThread(StartNode, NULL))
- wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin");
+ wxMessageBox(_("Error: CreateThread(StartNode) failed"), "Bitcoin");
if (fServer)
CreateThread(ThreadRPCServer, NULL);
-#if defined(__WXMSW__) && defined(GUI)
- if (fFirstRun)
- SetStartOnSystemStartup(true);
-#endif
-
-#ifndef GUI
+#if !defined(QT_GUI)
while (1)
Sleep(5000);
#endif
#include "init.h"
#include "strlcpy.h"
-#ifdef __WXMSW__
+#ifdef WIN32
#include <string.h>
#endif
bool fProxy = (fUseProxy && addrConnect.IsRoutable());
struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
-#ifdef __WXMSW__
+#ifdef WIN32
u_long fNonblock = 1;
if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
#else
return false;
}
socklen_t nRetSize = sizeof(nRet);
-#ifdef __WXMSW__
+#ifdef WIN32
if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
#else
if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
return false;
}
}
-#ifdef __WXMSW__
+#ifdef WIN32
else if (WSAGetLastError() != WSAEISCONN)
#else
else
CNode::ConnectNode immediately turns the socket back to non-blocking
but we'll turn it back to blocking just in case
*/
-#ifdef __WXMSW__
+#ifdef WIN32
fNonblock = 0;
if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
#else
void AddressCurrentlyConnected(const CAddress& addr)
{
+ CAddress *paddrFound = NULL;
+
CRITICAL_BLOCK(cs_mapAddresses)
{
// Only if it's been published already
map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
if (it != mapAddresses.end())
+ paddrFound = &(*it).second;
+ }
+
+ if (paddrFound)
+ {
+ int64 nUpdateInterval = 20 * 60;
+ if (paddrFound->nTime < GetAdjustedTime() - nUpdateInterval)
{
- CAddress& addrFound = (*it).second;
- int64 nUpdateInterval = 20 * 60;
- if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval)
- {
- // Periodically update most recently seen time
- addrFound.nTime = GetAdjustedTime();
- CAddrDB addrdb;
- addrdb.WriteAddress(addrFound);
- }
+ // Periodically update most recently seen time
+ paddrFound->nTime = GetAdjustedTime();
+ CAddrDB addrdb;
+ addrdb.WriteAddress(*paddrFound);
}
}
}
printf("connected %s\n", addrConnect.ToString().c_str());
// Set to nonblocking
-#ifdef __WXMSW__
+#ifdef WIN32
u_long nOne = 1;
if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
}
+std::map<unsigned int, int64> CNode::setBanned;
+CCriticalSection CNode::cs_setBanned;
+
+void CNode::ClearBanned()
+{
+ setBanned.clear();
+}
+
+bool CNode::IsBanned(unsigned int ip)
+{
+ bool fResult = false;
+ CRITICAL_BLOCK(cs_setBanned)
+ {
+ std::map<unsigned int, int64>::iterator i = setBanned.find(ip);
+ if (i != setBanned.end())
+ {
+ int64 t = (*i).second;
+ if (GetTime() < t)
+ fResult = true;
+ }
+ }
+ return fResult;
+}
+
+bool CNode::Misbehaving(int howmuch)
+{
+ if (addr.IsLocal())
+ {
+ printf("Warning: local node %s misbehaving\n", addr.ToString().c_str());
+ return false;
+ }
+
+ nMisbehavior += howmuch;
+ if (nMisbehavior >= GetArg("-banscore", 100))
+ {
+ int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
+ CRITICAL_BLOCK(cs_setBanned)
+ if (setBanned[addr.ip] < banTime)
+ setBanned[addr.ip] = banTime;
+ CloseSocketDisconnect();
+ printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
+ return true;
+ }
+ return false;
+}
+
{
closesocket(hSocket);
}
+ else if (CNode::IsBanned(addr.ip))
+ {
+ printf("connetion from %s dropped (banned)\n", addr.ToString().c_str());
+ closesocket(hSocket);
+ }
else
{
printf("accepted connection %s\n", addr.ToString().c_str());
if (!fTestNet)
{
printf("Loading addresses from DNS seeds (could take a while)\n");
- CAddrDB addrDB;
- addrDB.TxnBegin();
for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
vector<CAddress> vaddr;
if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
{
+ CAddrDB addrDB;
+ addrDB.TxnBegin();
BOOST_FOREACH (CAddress& addr, vaddr)
{
if (addr.GetByte(3) != 127)
found++;
}
}
+ addrDB.TxnCommit(); // Save addresses (it's ok if this fails)
}
}
-
- addrDB.TxnCommit(); // Save addresses (it's ok if this fails)
}
printf("%d addresses found from DNS seeds\n", found);
if (fShutdown)
return;
+ bool fAddSeeds = false;
+
CRITICAL_BLOCK(cs_mapAddresses)
{
// Add seed nodes if IRC isn't working
bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
- if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
+ if (mapAddresses.empty() && (GetTime() - nStart > 60 || fUseProxy) && !fTestNet)
+ fAddSeeds = true;
+ }
+
+ if (fAddSeeds)
+ {
+ for (int i = 0; i < ARRAYLEN(pnSeed); i++)
{
- for (int i = 0; i < ARRAYLEN(pnSeed); i++)
- {
- // It'll only connect to one or two seed nodes because once it connects,
- // it'll get a pile of addresses with newer timestamps.
- // Seed nodes are given a random 'last seen time' of between one and two
- // weeks ago.
- const int64 nOneWeek = 7*24*60*60;
- CAddress addr;
- addr.ip = pnSeed[i];
- addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
- AddAddress(addr);
- }
+ // It'll only connect to one or two seed nodes because once it connects,
+ // it'll get a pile of addresses with newer timestamps.
+ // Seed nodes are given a random 'last seen time' of between one and two
+ // weeks ago.
+ const int64 nOneWeek = 7*24*60*60;
+ CAddress addr;
+ addr.ip = pnSeed[i];
+ addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
+ AddAddress(addr);
}
}
-
//
// Choose an address to connect to based on most recently seen
//
BOOST_FOREACH(CNode* pnode, vNodes)
setConnected.insert(pnode->addr.ip & 0x0000ffff);
+ int64 nANow = GetAdjustedTime();
+
CRITICAL_BLOCK(cs_mapAddresses)
{
BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
const CAddress& addr = item.second;
if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
continue;
- int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;
- int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;
+ int64 nSinceLastSeen = nANow - addr.nTime;
+ int64 nSinceLastTry = nANow - addr.nLastTry;
// Randomize the order in a deterministic way, putting the standard port first
int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
//
if (fShutdown)
return false;
- if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
+ if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() ||
+ FindNode(addrConnect.ip) || CNode::IsBanned(addrConnect.ip))
return false;
vnThreadsRunning[1]--;
int nOne = 1;
addrLocalHost.port = htons(GetListenPort());
-#ifdef __WXMSW__
+#ifdef WIN32
// Initialize Windows Sockets
WSADATA wsadata;
int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
#endif
-#ifndef __WXMSW__
+#ifndef WIN32
// Allow binding if the port is still in TIME_WAIT state after
// the program was closed and restarted. Not an issue on windows.
setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
#endif
-#ifdef __WXMSW__
+#ifdef WIN32
// Set to nonblocking, incoming connections will also inherit this
if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
#else
if (pnodeLocalHost == NULL)
pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
-#ifdef __WXMSW__
+#ifdef WIN32
// Get local host ip
char pszHostName[1000] = "";
if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
if (closesocket(hListenSocket) == SOCKET_ERROR)
printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
-#ifdef __WXMSW__
+#ifdef WIN32
// Shutdown Windows Sockets
WSACleanup();
#endif
ppmutexOpenSSL[i] = new boost::interprocess::interprocess_mutex();
CRYPTO_set_locking_callback(locking_callback);
-#ifdef __WXMSW__
+#ifdef WIN32
// Seed random number generator with screen scrape and other hardware sources
RAND_screen();
#endif
return;
nLastPerfmon = GetTime();
-#ifdef __WXMSW__
+#ifdef WIN32
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
// Seed with the entire set of perfmon data
unsigned char pdata[250000];
}
}
-#ifdef __WXMSW__
+#ifdef WIN32
if (fPrintToDebugger)
{
static CCriticalSection cs_OutputDebugStringF;
return ret;
}
-
-string strprintf(const char* format, ...)
+string strprintf(const std::string &format, ...)
{
char buffer[50000];
char* p = buffer;
{
va_list arg_ptr;
va_start(arg_ptr, format);
- ret = _vsnprintf(p, limit, format, arg_ptr);
+ ret = _vsnprintf(p, limit, format.c_str(), arg_ptr);
va_end(arg_ptr);
if (ret >= 0 && ret < limit)
break;
return str;
}
-
-bool error(const char* format, ...)
+bool error(const std::string &format, ...)
{
char buffer[50000];
int limit = sizeof(buffer);
va_list arg_ptr;
va_start(arg_ptr, format);
- int ret = _vsnprintf(buffer, limit, format, arg_ptr);
+ int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
va_end(arg_ptr);
if (ret < 0 || ret >= limit)
{
return ParseHex(str.c_str());
}
-
void ParseParameters(int argc, char* argv[])
{
mapArgs.clear();
pszValue = strchr(psz, '=');
*pszValue++ = '\0';
}
- #ifdef __WXMSW__
+ #ifdef WIN32
_strlwr(psz);
if (psz[0] == '/')
psz[0] = '-';
}
}
+ bool SoftSetArg(const std::string& strArg, const std::string& strValue)
+ {
+ if (mapArgs.count(strArg))
+ return false;
+ mapArgs[strArg] = strValue;
+ return true;
+ }
+
+ bool SoftSetArg(const std::string& strArg, bool fValue)
+ {
+ if (fValue)
+ return SoftSetArg(strArg, std::string("1"));
+ else
+ return SoftSetArg(strArg, std::string("0"));
+ }
+
+
+string EncodeBase64(const unsigned char* pch, size_t len)
+{
+ static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ string strRet="";
+ strRet.reserve((len+2)/3*4);
+
+ int mode=0, left=0;
+ const unsigned char *pchEnd = pch+len;
-const char* wxGetTranslation(const char* pszEnglish)
+ while (pch<pchEnd)
+ {
+ int enc = *(pch++);
+ switch (mode)
+ {
+ case 0: // we have no bits
+ strRet += pbase64[enc >> 2];
+ left = (enc & 3) << 4;
+ mode = 1;
+ break;
+
+ case 1: // we have two bits
+ strRet += pbase64[left | (enc >> 4)];
+ left = (enc & 15) << 2;
+ mode = 2;
+ break;
+
+ case 2: // we have four bits
+ strRet += pbase64[left | (enc >> 6)];
+ strRet += pbase64[enc & 63];
+ mode = 0;
+ break;
+ }
+ }
+
+ if (mode)
+ {
+ strRet += pbase64[left];
+ strRet += '=';
+ if (mode == 1)
+ strRet += '=';
+ }
+
+ return strRet;
+}
+
+string EncodeBase64(const string& str)
{
-#ifdef GUI
- // Wrapper of wxGetTranslation returning the same const char* type as was passed in
- static CCriticalSection cs;
- CRITICAL_BLOCK(cs)
+ return EncodeBase64((const unsigned char*)str.c_str(), str.size());
+}
+
+vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
+{
+ static const int decode64_table[256] =
+ {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
+ -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
+
+ if (pfInvalid)
+ *pfInvalid = false;
+
+ vector<unsigned char> vchRet;
+ vchRet.reserve(strlen(p)*3/4);
+
+ int mode = 0;
+ int left = 0;
+
+ while (1)
{
- // Look in cache
- static map<string, char*> mapCache;
- map<string, char*>::iterator mi = mapCache.find(pszEnglish);
- if (mi != mapCache.end())
- return (*mi).second;
-
- // wxWidgets translation
- wxString strTranslated = wxGetTranslation(wxString(pszEnglish, wxConvUTF8));
-
- // We don't cache unknown strings because caller might be passing in a
- // dynamic string and we would keep allocating memory for each variation.
- if (strcmp(pszEnglish, strTranslated.utf8_str()) == 0)
- return pszEnglish;
-
- // Add to cache, memory doesn't need to be freed. We only cache because
- // we must pass back a pointer to permanently allocated memory.
- char* pszCached = new char[strlen(strTranslated.utf8_str())+1];
- strcpy(pszCached, strTranslated.utf8_str());
- mapCache[pszEnglish] = pszCached;
- return pszCached;
+ int dec = decode64_table[*p];
+ if (dec == -1) break;
+ p++;
+ switch (mode)
+ {
+ case 0: // we have no bits and get 6
+ left = dec;
+ mode = 1;
+ break;
+
+ case 1: // we have 6 bits and keep 4
+ vchRet.push_back((left<<2) | (dec>>4));
+ left = dec & 15;
+ mode = 2;
+ break;
+
+ case 2: // we have 4 bits and get 6, we keep 2
+ vchRet.push_back((left<<4) | (dec>>2));
+ left = dec & 3;
+ mode = 3;
+ break;
+
+ case 3: // we have 2 bits and get 6
+ vchRet.push_back((left<<6) | dec);
+ mode = 0;
+ break;
+ }
}
- return NULL;
-#else
- return pszEnglish;
-#endif
+
+ if (pfInvalid)
+ switch (mode)
+ {
+ case 0: // 4n base64 characters processed: ok
+ break;
+
+ case 1: // 4n+1 base64 character processed: impossible
+ *pfInvalid = true;
+ break;
+
+ case 2: // 4n+2 base64 characters processed: require '=='
+ if (left || p[0] != '=' || p[1] != '=' || decode64_table[p[2]] != -1)
+ *pfInvalid = true;
+ break;
+
+ case 3: // 4n+3 base64 characters processed: require '='
+ if (left || p[0] != '=' || decode64_table[p[1]] != -1)
+ *pfInvalid = true;
+ break;
+ }
+
+ return vchRet;
+}
+
+string DecodeBase64(const string& str)
+{
+ vector<unsigned char> vchRet = DecodeBase64(str.c_str());
+ return string((const char*)&vchRet[0], vchRet.size());
}
void FormatException(char* pszMessage, std::exception* pex, const char* pszThread)
{
-#ifdef __WXMSW__
+#ifdef WIN32
char pszModule[MAX_PATH];
pszModule[0] = '\0';
GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
printf("\n\n************************\n%s\n", pszMessage);
fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
strMiscWarning = pszMessage;
-#ifdef GUI
- if (wxTheApp && !fDaemon)
- MyMessageBox(pszMessage, "Bitcoin", wxOK | wxICON_ERROR);
-#endif
throw;
}
printf("\n\n************************\n%s\n", pszMessage);
fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
strMiscWarning = pszMessage;
-#ifdef GUI
- if (wxTheApp && !fDaemon)
- boost::thread(boost::bind(ThreadOneMessageBox, string(pszMessage)));
-#endif
}
-#ifdef __WXMSW__
+#ifdef WIN32
typedef WINSHELLAPI BOOL (WINAPI *PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
string MyGetSpecialFolderPath(int nFolder, bool fCreate)
// Windows: C:\Documents and Settings\username\Application Data\Bitcoin
// Mac: ~/Library/Application Support/Bitcoin
// Unix: ~/.bitcoin
-#ifdef __WXMSW__
+#ifdef WIN32
// Windows
return MyGetSpecialFolderPath(CSIDL_APPDATA, true) + "\\Bitcoin";
#else
string strHome = pszHome;
if (strHome[strHome.size()-1] != '/')
strHome += '/';
-#ifdef __WXMAC_OSX__
+#ifdef MAC_OSX
// Mac
strHome += "Library/Application Support/";
filesystem::create_directory(strHome.c_str());
// - Median of other nodes's clocks
// - The user (asking the user to fix the system clock if the first two disagree)
//
+static int64 nMockTime = 0; // For unit testing
+
int64 GetTime()
{
+ if (nMockTime) return nMockTime;
+
return time(NULL);
}
+void SetMockTime(int64 nMockTimeIn)
+{
+ nMockTime = nMockTimeIn;
+}
+
static int64 nTimeOffset = 0;
int64 GetAdjustedTime()
#include "uint256.h"
-#ifndef __WXMSW__
+#ifndef WIN32
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#endif
// This is needed because the foreach macro can't get over the comma in pair<t1, t2>
-#define PAIRTYPE(t1, t2) pair<t1, t2>
+#define PAIRTYPE(t1, t2) std::pair<t1, t2>
// Align by increasing pointer, must have extra space at end of buffer
template <size_t nBytes, typename T>
return u.ptr;
}
-#ifdef __WXMSW__
+#ifdef WIN32
#define MSG_NOSIGNAL 0
#define MSG_DONTWAIT 0
#ifndef UINT64_MAX
{
if (hSocket == INVALID_SOCKET)
return WSAENOTSOCK;
-#ifdef __WXMSW__
+#ifdef WIN32
int ret = closesocket(hSocket);
#else
int ret = close(hSocket);
return ret;
}
#define closesocket(s) myclosesocket(s)
-
-#ifndef GUI
+#if !defined(QT_GUI)
inline const char* _(const char* psz)
{
return psz;
-
extern std::map<std::string, std::string> mapArgs;
extern std::map<std::string, std::vector<std::string> > mapMultiArgs;
extern bool fDebug;
void RandAddSeedPerfmon();
int OutputDebugStringF(const char* pszFormat, ...);
int my_snprintf(char* buffer, size_t limit, const char* format, ...);
-std::string strprintf(const char* format, ...);
-bool error(const char* format, ...);
+std::string strprintf(const std::string &format, ...);
+bool error(const std::string &format, ...);
void LogException(std::exception* pex, const char* pszThread);
void PrintException(std::exception* pex, const char* pszThread);
void PrintExceptionContinue(std::exception* pex, const char* pszThread);
bool ParseMoney(const char* pszIn, int64& nRet);
std::vector<unsigned char> ParseHex(const char* psz);
std::vector<unsigned char> ParseHex(const std::string& str);
+std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = NULL);
+std::string DecodeBase64(const std::string& str);
+std::string EncodeBase64(const unsigned char* pch, size_t len);
+std::string EncodeBase64(const std::string& str);
void ParseParameters(int argc, char* argv[]);
const char* wxGetTranslation(const char* psz);
bool WildcardMatch(const char* psz, const char* mask);
std::string GetPidFile();
void CreatePidFile(std::string pidFile, pid_t pid);
void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet);
-#ifdef __WXMSW__
+#ifdef WIN32
std::string MyGetSpecialFolderPath(int nFolder, bool fCreate);
#endif
std::string GetDefaultDataDir();
int GetRandInt(int nMax);
uint64 GetRand(uint64 nMax);
int64 GetTime();
+void SetMockTime(int64 nMockTimeIn);
int64 GetAdjustedTime();
void AddTimeData(unsigned int ip, int64 nTime);
std::string FormatFullVersion();
+// This is exactly like std::string, but with a custom allocator.
+// (secure_allocator<> is defined in serialize.h)
+typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString;
+
inline int64 GetPerformanceCounter()
{
int64 nCounter = 0;
-#ifdef __WXMSW__
+#ifdef WIN32
QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
#else
timeval t;
inline bool IsSwitchChar(char c)
{
-#ifdef __WXMSW__
+#ifdef WIN32
return c == '-' || c == '/';
#else
return c == '-';
return nDefault;
}
- inline bool GetBoolArg(const std::string& strArg)
+ inline bool GetBoolArg(const std::string& strArg, bool fDefault=false)
{
if (mapArgs.count(strArg))
{
return true;
return (atoi(mapArgs[strArg]) != 0);
}
- return false;
+ return fDefault;
}
+ /**
+ * Set an argument if it doesn't already have a value
+ *
+ * @param strArg Argument to set (e.g. "-foo")
+ * @param strValue Value (e.g. "1")
+ * @return true if argument gets set, false if it already had a value
+ */
+ bool SoftSetArg(const std::string& strArg, const std::string& strValue);
+
+ /**
+ * Set a boolean argument if it doesn't already have a value
+ *
+ * @param strArg Argument to set (e.g. "-foo")
+ * @param fValue Value (e.g. false)
+ * @return true if argument gets set, false if it already had a value
+ */
+ bool SoftSetArg(const std::string& strArg, bool fValue);
inline void heapchk()
{
-#ifdef __WXMSW__
+#ifdef WIN32
/// for debugging
//if (_heapchk() != _HEAPOK)
// DebugBreak();
}
+// Median filter over a stream of values
+// Returns the median of the last N numbers
+template <typename T> class CMedianFilter
+{
+private:
+ std::vector<T> vValues;
+ std::vector<T> vSorted;
+ int nSize;
+public:
+ CMedianFilter(int size, T initial_value):
+ nSize(size)
+ {
+ vValues.reserve(size);
+ vValues.push_back(initial_value);
+ vSorted = vValues;
+ }
+
+ void input(T value)
+ {
+ if(vValues.size() == nSize)
+ {
+ vValues.erase(vValues.begin());
+ }
+ vValues.push_back(value);
+
+ vSorted.resize(vValues.size());
+ std::copy(vValues.begin(), vValues.end(), vSorted.begin());
+ std::sort(vSorted.begin(), vSorted.end());
+ }
+
+ T median() const
+ {
+ int size = vSorted.size();
+ assert(size>0);
+ if(size & 1) // Odd number of elements
+ {
+ return vSorted[size/2];
+ }
+ else // Even number of elements
+ {
+ return (vSorted[size/2-1] + vSorted[size/2]) / 2;
+ }
+ }
+};
+
// Note: It turns out we might have been able to use boost::thread
// by using TerminateThread(boost::thread.native_handle(), 0);
-#ifdef __WXMSW__
+#ifdef WIN32
typedef HANDLE pthread_t;
inline pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=false)
inline bool AffinityBugWorkaround(void(*pfn)(void*))
{
-#ifdef __WXMSW__
+#ifdef WIN32
// Sometimes after a few hours affinity gets stuck on one processor
DWORD_PTR dwProcessAffinityMask = -1;
DWORD_PTR dwSystemAffinityMask = -1;
return false;
}
+inline uint32_t ByteReverse(uint32_t value)
+{
+ value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
+ return (value<<16) | (value>>16);
+}
+
#endif