aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authors_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>2009-10-29 02:52:48 +0000
committers_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>2009-10-29 02:52:48 +0000
commitdd519206a684c772a4a06ceecc87c665ad09d8be (patch)
tree08535edfd634944708c936fd596f3719ccf191d8
parentfa2a0338d3f8b1c3a1d75bff39ff42e436cee0dc (diff)
downloadbitcoin-dd519206a684c772a4a06ceecc87c665ad09d8be.tar.xz
addr relaying fixes, proxy option and privacy patches, detect connect to self, non-final tx locktime changes, fix hide unconfirmed generated
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@18 1a98c847-1fd6-4fd8-948a-caf3550aa51b
-rw-r--r--build.txt12
-rw-r--r--db.cpp19
-rw-r--r--headers.h2
-rw-r--r--irc.cpp10
-rw-r--r--key.h2
-rw-r--r--main.cpp71
-rw-r--r--main.h16
-rw-r--r--makefile4
-rw-r--r--net.cpp173
-rw-r--r--net.h131
-rw-r--r--serialize.h2
-rw-r--r--strlcpy.h84
-rw-r--r--ui.cpp223
-rw-r--r--ui.h8
-rw-r--r--uibase.cpp51
-rw-r--r--uibase.h98
-rw-r--r--uiproject.fbp308
-rw-r--r--util.cpp170
-rw-r--r--util.h164
19 files changed, 1209 insertions, 339 deletions
diff --git a/build.txt b/build.txt
index b6b526f1bc..f510055767 100644
--- a/build.txt
+++ b/build.txt
@@ -1,4 +1,4 @@
-BitCoin v0.1.6 ALPHA
+BitCoin v0.1.6 BETA
Copyright (c) 2009 Satoshi Nakamoto
Distributed under the MIT/X11 software license, see the accompanying
@@ -19,10 +19,10 @@ Dependencies
Libraries you need to obtain separately to build:
default path download
-wxWidgets \wxWidgets http://www.wxwidgets.org/downloads/
-OpenSSL \OpenSSL http://www.openssl.org/source/
-Berkeley DB \DB http://www.oracle.com/technology/software/products/berkeley-db/index.html
-Boost \Boost http://www.boost.org/users/download/
+wxWidgets \wxwidgets http://www.wxwidgets.org/downloads/
+OpenSSL \openssl http://www.openssl.org/source/
+Berkeley DB \db http://www.oracle.com/technology/software/products/berkeley-db/index.html
+Boost \boost http://www.boost.org/users/download/
Their licenses:
wxWidgets LGPL 2.1 with very liberal exceptions
@@ -75,7 +75,7 @@ If you want to use it with MSVC, generate the .lib file
Berkeley DB
-----------
Using MinGW and MSYS:
-cd \DB\build_unix
+cd \db\build_unix
sh ../dist/configure --enable-mingw --enable-cxx
make
diff --git a/db.cpp b/db.cpp
index a9f5b7953c..315e93b73a 100644
--- a/db.cpp
+++ b/db.cpp
@@ -121,10 +121,12 @@ void CDB::Close()
pdb->close(0);
delete pdb;
pdb = NULL;
- dbenv.txn_checkpoint(0, 0, 0);
CRITICAL_BLOCK(cs_db)
+ {
+ dbenv.txn_checkpoint(0, 0, 0);
--mapFileUseCount[strFile];
+ }
RandAddSeed();
}
@@ -376,11 +378,11 @@ bool CTxDB::LoadBlockIndex()
{
if (pindexGenesisBlock == NULL)
return true;
- return error("CTxDB::LoadBlockIndex() : hashBestChain not found\n");
+ return error("CTxDB::LoadBlockIndex() : hashBestChain not found");
}
if (!mapBlockIndex.count(hashBestChain))
- return error("CTxDB::LoadBlockIndex() : blockindex for hashBestChain not found\n");
+ return error("CTxDB::LoadBlockIndex() : blockindex for hashBestChain not found");
pindexBest = mapBlockIndex[hashBestChain];
nBestHeight = pindexBest->nHeight;
printf("LoadBlockIndex(): hashBestChain=%s height=%d\n", hashBestChain.ToString().substr(0,14).c_str(), nBestHeight);
@@ -500,16 +502,15 @@ bool CReviewDB::WriteReviews(uint256 hash, const vector<CReview>& vReviews)
CWalletDB::~CWalletDB()
{
// Flush whenever all handles to wallet.dat are closed
- Close();
CRITICAL_BLOCK(cs_db)
{
+ Close(); // close includes a txn_checkpoint
map<string, int>::iterator mi = mapFileUseCount.find(strFile);
if (mi != mapFileUseCount.end())
{
int nRefCount = (*mi).second;
if (nRefCount == 0)
{
- dbenv.txn_checkpoint(0, 0, 0);
dbenv.lsn_reset(strFile.c_str(), 0);
mapFileUseCount.erase(mi++);
}
@@ -600,6 +601,9 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
if (strKey == "nLimitProcessors") ssValue >> nLimitProcessors;
if (strKey == "fMinimizeToTray") ssValue >> fMinimizeToTray;
if (strKey == "fMinimizeOnClose") ssValue >> fMinimizeOnClose;
+ if (strKey == "fUseProxy") ssValue >> fUseProxy;
+ if (strKey == "addrProxy") ssValue >> addrProxy;
+
}
}
}
@@ -610,6 +614,9 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
printf("addrIncoming = %s\n", addrIncoming.ToString().c_str());
printf("fMinimizeToTray = %d\n", fMinimizeToTray);
printf("fMinimizeOnClose = %d\n", fMinimizeOnClose);
+ printf("fUseProxy = %d\n", fUseProxy);
+ printf("addrProxy = %s\n", addrProxy.ToString().c_str());
+
// The transaction fee setting won't be needed for many years to come.
// Setting it to zero here in case they set it to something in an earlier version.
@@ -639,7 +646,7 @@ bool LoadWallet(bool& fFirstRunRet)
else
{
// Create new keyUser and set as default key
- RandAddSeed(true);
+ RandAddSeedPerfmon();
keyUser.MakeNewKey();
if (!AddKey(keyUser))
return false;
diff --git a/headers.h b/headers.h
index f7e88e0c67..29b16fb780 100644
--- a/headers.h
+++ b/headers.h
@@ -5,6 +5,7 @@
#ifdef _MSC_VER
#pragma warning(disable:4786)
#pragma warning(disable:4804)
+#pragma warning(disable:4805)
#pragma warning(disable:4717)
#endif
#ifdef _WIN32_WINNT
@@ -62,6 +63,7 @@ using namespace boost;
+#include "strlcpy.h"
#include "serialize.h"
#include "uint256.h"
#include "util.h"
diff --git a/irc.cpp b/irc.cpp
index cfc9464aa7..707b4fe19f 100644
--- a/irc.cpp
+++ b/irc.cpp
@@ -163,6 +163,9 @@ void ThreadIRCSeed(void* parg)
int nErrorWait = 10;
int nRetryWait = 10;
+ if (fUseProxy && addrProxy.port == htons(9050))
+ return;
+
while (!fShutdown)
{
CAddress addrConnect("216.155.130.130:6667");
@@ -191,9 +194,10 @@ void ThreadIRCSeed(void* parg)
return;
}
- string strMyName = EncodeAddress(addrLocalHost);
-
- if (!addrLocalHost.IsRoutable())
+ string strMyName;
+ if (addrLocalHost.IsRoutable() && !fUseProxy)
+ strMyName = EncodeAddress(addrLocalHost);
+ else
strMyName = strprintf("x%u", GetRand(1000000000));
diff --git a/key.h b/key.h
index 39ca86d317..71fce64a2a 100644
--- a/key.h
+++ b/key.h
@@ -35,7 +35,7 @@ public:
};
-// secure_allocator is defined is serialize.h
+// secure_allocator is defined in serialize.h
typedef vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
diff --git a/main.cpp b/main.cpp
index dbdee70211..710b789200 100644
--- a/main.cpp
+++ b/main.cpp
@@ -415,6 +415,10 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis
if (!CheckTransaction())
return error("AcceptTransaction() : CheckTransaction failed");
+ // To help v0.1.5 clients who would see it as negative number. please delete this later.
+ if (nLockTime > INT_MAX)
+ return error("AcceptTransaction() : not accepting nLockTime beyond 2038");
+
// Do we already have it?
uint256 hash = GetHash();
CRITICAL_BLOCK(cs_mapTransactions)
@@ -1214,6 +1218,12 @@ bool CBlock::AcceptBlock()
if (nTime <= pindexPrev->GetMedianTimePast())
return error("AcceptBlock() : block's timestamp is too early");
+ // Check that all transactions are finalized (starting around 30 Nov 2009)
+ if (nBestHeight > 31000) // 25620 + 5320
+ foreach(const CTransaction& tx, vtx)
+ if (!tx.IsFinal(nTime))
+ return error("AcceptBlock() : contains a non-final transaction");
+
// Check proof of work
if (nBits != GetNextWorkRequired(pindexPrev))
return error("AcceptBlock() : incorrect proof of work");
@@ -1649,7 +1659,7 @@ bool ProcessMessages(CNode* pfrom)
CDataStream& vRecv = pfrom->vRecv;
if (vRecv.empty())
return true;
- printf("ProcessMessages(%d bytes)\n", vRecv.size());
+ //printf("ProcessMessages(%d bytes)\n", vRecv.size());
//
// Message format
@@ -1692,7 +1702,7 @@ bool ProcessMessages(CNode* pfrom)
{
// Rewind and wait for rest of message
///// need a mechanism to give up waiting for overlong message size error
- printf("MESSAGE-BREAK\n");
+ //printf("message-break\n");
vRecv.insert(vRecv.begin(), BEGIN(hdr), END(hdr));
Sleep(100);
break;
@@ -1711,7 +1721,20 @@ bool ProcessMessages(CNode* pfrom)
fRet = ProcessMessage(pfrom, strCommand, vMsg);
CheckForShutdown(2);
}
- CATCH_PRINT_EXCEPTION("ProcessMessage()")
+ catch (std::ios_base::failure& e) {
+ if (strstr(e.what(), "CDataStream::read() : end of data"))
+ {
+ // Allow exceptions from underlength message on vRecv
+ LogException(&e, "ProcessMessage()");
+ }
+ else
+ PrintException(&e, "ProcessMessage()");
+ } catch (std::exception& e) {
+ PrintException(&e, "ProcessMessage()");
+ } catch (...) {
+ PrintException(NULL, "ProcessMessage()");
+ }
+
if (!fRet)
printf("ProcessMessage(%s, %d bytes) FAILED\n", strCommand.c_str(), nMessageSize);
}
@@ -1726,7 +1749,8 @@ bool ProcessMessages(CNode* pfrom)
bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
static map<unsigned int, vector<unsigned char> > mapReuseKey;
- printf("received: %-12s (%d bytes)\n", strCommand.c_str(), vRecv.size());
+ RandAddSeedPerfmon();
+ printf("received: %s (%d bytes)\n", strCommand.c_str(), vRecv.size());
if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0)
{
printf("dropmessages DROPPING RECV MESSAGE\n");
@@ -1735,18 +1759,32 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
+
if (strCommand == "version")
{
- // Can only do this once
+ // Each connection can only send one version message
if (pfrom->nVersion != 0)
return false;
int64 nTime;
CAddress addrMe;
+ CAddress addrFrom;
+ uint64 nNonce = 1;
vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;
+ if (pfrom->nVersion >= 106 && !vRecv.empty())
+ vRecv >> addrFrom >> nNonce;
if (pfrom->nVersion == 0)
return false;
+ // Disconnect if we connected to ourself
+ if (nNonce == nLocalHostNonce)
+ {
+ pfrom->fDisconnect = true;
+ pfrom->vRecv.clear();
+ pfrom->vSend.clear();
+ return true;
+ }
+
pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION));
pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));
@@ -1767,6 +1805,8 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), uint256(0));
}
+ pfrom->fSuccessfullyConnected = true;
+
printf("version message: version %d\n", pfrom->nVersion);
}
@@ -1800,16 +1840,16 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (fShutdown)
return true;
AddAddress(addrdb, addr);
- if (addr.IsRoutable() && addr.ip != addrLocalHost.ip)
+ pfrom->AddAddressKnown(addr);
+ if (!pfrom->fGetAddr && addr.IsRoutable())
{
// Put on lists to send to other nodes
- pfrom->setAddrKnown.insert(addr);
CRITICAL_BLOCK(cs_vNodes)
foreach(CNode* pnode, vNodes)
- if (!pnode->setAddrKnown.count(addr))
- pnode->vAddrToSend.push_back(addr);
+ pnode->PushAddress(addr);
}
}
+ pfrom->fGetAddr = false;
}
@@ -2009,7 +2049,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
return true;
const CAddress& addr = item.second;
if (addr.nTime > nSince)
- pfrom->vAddrToSend.push_back(addr);
+ pfrom->PushAddress(addr);
}
}
}
@@ -2108,8 +2148,11 @@ bool SendMessages(CNode* pto)
vector<CAddress> vAddrToSend;
vAddrToSend.reserve(pto->vAddrToSend.size());
foreach(const CAddress& addr, pto->vAddrToSend)
- if (!pto->setAddrKnown.count(addr))
+ {
+ // returns true if wasn't already contained in the set
+ if (pto->setAddrKnown.insert(addr).second)
vAddrToSend.push_back(addr);
+ }
pto->vAddrToSend.clear();
if (!vAddrToSend.empty())
pto->PushMessage("addr", vAddrToSend);
@@ -2193,7 +2236,7 @@ void GenerateBitcoins(bool fGenerate)
if (fLimitProcessors && nProcessors > nLimitProcessors)
nProcessors = nLimitProcessors;
int nAddThreads = nProcessors - vnThreadsRunning[3];
- printf("starting %d bitcoinminer threads\n", nAddThreads);
+ printf("Starting %d BitcoinMiner threads\n", nAddThreads);
for (int i = 0; i < nAddThreads; i++)
if (_beginthread(ThreadBitcoinMiner, 0, NULL) == -1)
printf("Error: _beginthread(ThreadBitcoinMiner) failed\n");
@@ -2207,7 +2250,7 @@ void ThreadBitcoinMiner(void* parg)
try
{
bool fRet = BitcoinMiner();
- printf("BitcoinMiner returned %s\n\n\n", fRet ? "true" : "false");
+ printf("BitcoinMiner returned %s\n", fRet ? "true" : "false");
vnThreadsRunning[3]--;
}
catch (std::exception& e) {
@@ -2737,7 +2780,7 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
else
strError = "Error: Transaction creation failed ";
wxMessageBox(strError, "Sending...");
- return error("SendMoney() : %s\n", strError.c_str());
+ return error("SendMoney() : %s", strError.c_str());
}
if (!CommitTransactionSpent(wtxNew, key))
{
diff --git a/main.h b/main.h
index 6b11285e5e..958f7a5f1c 100644
--- a/main.h
+++ b/main.h
@@ -366,7 +366,7 @@ public:
int nVersion;
vector<CTxIn> vin;
vector<CTxOut> vout;
- int nLockTime;
+ unsigned int nLockTime;
CTransaction()
@@ -401,9 +401,15 @@ public:
return SerializeHash(*this);
}
- bool IsFinal() const
+ bool IsFinal(int64 nBlockTime=0) const
{
- if (nLockTime == 0 || nLockTime < nBestHeight)
+ // Time based nLockTime implemented in 0.1.6,
+ // do not use time based until most 0.1.5 nodes have upgraded.
+ if (nBlockTime == 0)
+ nBlockTime = GetAdjustedTime();
+ if (nLockTime == 0)
+ return true;
+ if (nLockTime < (nLockTime < 500000000 ? nBestHeight : nBlockTime))
return true;
foreach(const CTxIn& txin, vin)
if (!txin.IsFinal())
@@ -686,8 +692,9 @@ public:
char fSpent;
//// probably need to sign the order info so know it came from payer
- // memory only
+ // memory only UI hints
mutable unsigned int nTimeDisplayed;
+ mutable int nLinesDisplayed;
CWalletTx()
@@ -712,6 +719,7 @@ public:
fFromMe = false;
fSpent = false;
nTimeDisplayed = 0;
+ nLinesDisplayed = 0;
}
IMPLEMENT_SERIALIZE
diff --git a/makefile b/makefile
index 64bb773047..2d932f02cd 100644
--- a/makefile
+++ b/makefile
@@ -17,8 +17,8 @@ endif
-INCLUDEPATHS=-I"/boost" -I"/DB/build_unix" -I"/OpenSSL/include" -I"/wxWidgets/lib/vc_lib/mswd" -I"/wxWidgets/include"
-LIBPATHS=-L"/DB/build_unix" -L"/OpenSSL/out" -L"/wxWidgets/lib/gcc_lib"
+INCLUDEPATHS=-I"/boost" -I"/db/build_unix" -I"/openssl/include" -I"/wxwidgets/lib/vc_lib/mswd" -I"/wxwidgets/include"
+LIBPATHS=-L"/db/build_unix" -L"/openssl/out" -L"/wxwidgets/lib/gcc_lib"
LIBS= \
-l db_cxx \
-l eay32 \
diff --git a/net.cpp b/net.cpp
index db138e13a5..22b84f9dee 100644
--- a/net.cpp
+++ b/net.cpp
@@ -8,6 +8,7 @@
void ThreadMessageHandler2(void* parg);
void ThreadSocketHandler2(void* parg);
void ThreadOpenConnections2(void* parg);
+bool OpenNetworkConnection(const CAddress& addrConnect);
@@ -22,8 +23,10 @@ uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
CAddress addrLocalHost(0, DEFAULT_PORT, nLocalServices);
CNode nodeLocalHost(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
CNode* pnodeLocalHost = &nodeLocalHost;
+uint64 nLocalHostNonce = 0;
bool fShutdown = false;
array<int, 10> vnThreadsRunning;
+SOCKET hListenSocket = INVALID_SOCKET;
vector<CNode*> vNodes;
CCriticalSection cs_vNodes;
@@ -34,9 +37,11 @@ deque<pair<int64, CInv> > vRelayExpiration;
CCriticalSection cs_mapRelay;
map<CInv, int64> mapAlreadyAskedFor;
+// Settings
+int fUseProxy = false;
+CAddress addrProxy("127.0.0.1:9050");
-CAddress addrProxy;
bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
{
@@ -47,7 +52,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
return false;
bool fRoutable = !(addrConnect.GetByte(3) == 10 || (addrConnect.GetByte(3) == 192 && addrConnect.GetByte(2) == 168));
- bool fProxy = (addrProxy.ip && fRoutable);
+ bool fProxy = (fUseProxy && fRoutable);
struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
@@ -69,18 +74,18 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
if (ret != nSize)
{
closesocket(hSocket);
- return error("Error sending to proxy\n");
+ return error("Error sending to proxy");
}
char pchRet[8];
if (recv(hSocket, pchRet, 8, 0) != 8)
{
closesocket(hSocket);
- return error("Error reading proxy response\n");
+ return error("Error reading proxy response");
}
if (pchRet[1] != 0x5a)
{
closesocket(hSocket);
- return error("Proxy returned error %d\n", pchRet[1]);
+ return error("Proxy returned error %d", pchRet[1]);
}
printf("Proxy connection established %s\n", addrConnect.ToStringLog().c_str());
}
@@ -95,7 +100,7 @@ bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const cha
{
SOCKET hSocket;
if (!ConnectSocket(addrConnect, hSocket))
- return error("GetMyExternalIP() : connection to %s failed\n", addrConnect.ToString().c_str());
+ return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
send(hSocket, pszGet, strlen(pszGet), 0);
@@ -131,7 +136,7 @@ bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const cha
}
}
closesocket(hSocket);
- return error("GetMyExternalIP() : connection closed\n");
+ return error("GetMyExternalIP() : connection closed");
}
@@ -141,6 +146,9 @@ bool GetMyExternalIP(unsigned int& ipRet)
char* pszGet;
char* pszKeyword;
+ if (fUseProxy)
+ return false;
+
for (int nLookup = 0; nLookup <= 1; nLookup++)
for (int nHost = 1; nHost <= 2; nHost++)
{
@@ -416,14 +424,14 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
}
}
-void CNode::Disconnect()
+void CNode::DoDisconnect()
{
printf("disconnecting node %s\n", addr.ToStringLog().c_str());
closesocket(hSocket);
// If outbound and never got version message, mark address as failed
- if (!fInbound && nVersion == 0)
+ if (!fInbound && !fSuccessfullyConnected)
CRITICAL_BLOCK(cs_mapAddresses)
mapAddresses[addr.GetKey()].nLastFailed = GetTime();
@@ -458,18 +466,18 @@ void ThreadSocketHandler(void* parg)
loop
{
- vnThreadsRunning[0] = true;
+ vnThreadsRunning[0]++;
CheckForShutdown(0);
try
{
ThreadSocketHandler2(parg);
- vnThreadsRunning[0] = false;
+ vnThreadsRunning[0]--;
}
catch (std::exception& e) {
- vnThreadsRunning[0] = false;
+ vnThreadsRunning[0]--;
PrintException(&e, "ThreadSocketHandler()");
} catch (...) {
- vnThreadsRunning[0] = false;
+ vnThreadsRunning[0]--;
PrintException(NULL, "ThreadSocketHandler()");
}
Sleep(5000);
@@ -479,7 +487,6 @@ void ThreadSocketHandler(void* parg)
void ThreadSocketHandler2(void* parg)
{
printf("ThreadSocketHandler started\n");
- SOCKET hListenSocket = *(SOCKET*)parg;
list<CNode*> vNodesDisconnected;
int nPrevNodeCount = 0;
@@ -498,7 +505,7 @@ void ThreadSocketHandler2(void* parg)
{
// remove from vNodes
vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
- pnode->Disconnect();
+ pnode->DoDisconnect();
// hold in disconnected pool until all refs are released
pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 5 * 60);
@@ -562,9 +569,9 @@ void ThreadSocketHandler2(void* parg)
}
}
- vnThreadsRunning[0] = false;
+ vnThreadsRunning[0]--;
int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, NULL, &timeout);
- vnThreadsRunning[0] = true;
+ vnThreadsRunning[0]++;
CheckForShutdown(0);
if (nSelect == SOCKET_ERROR)
{
@@ -577,7 +584,6 @@ void ThreadSocketHandler2(void* parg)
}
Sleep(timeout.tv_usec/1000);
}
- RandAddSeed();
//// debug print
//foreach(CNode* pnode, vNodes)
@@ -711,18 +717,18 @@ void ThreadOpenConnections(void* parg)
loop
{
- vnThreadsRunning[1] = true;
+ vnThreadsRunning[1]++;
CheckForShutdown(1);
try
{
ThreadOpenConnections2(parg);
- vnThreadsRunning[1] = false;
+ vnThreadsRunning[1]--;
}
catch (std::exception& e) {
- vnThreadsRunning[1] = false;
+ vnThreadsRunning[1]--;
PrintException(&e, "ThreadOpenConnections()");
} catch (...) {
- vnThreadsRunning[1] = false;
+ vnThreadsRunning[1]--;
PrintException(NULL, "ThreadOpenConnections()");
}
Sleep(5000);
@@ -733,6 +739,13 @@ void ThreadOpenConnections2(void* parg)
{
printf("ThreadOpenConnections started\n");
+ // Connect to one specified address
+ while (mapArgs.count("/connect"))
+ {
+ OpenNetworkConnection(CAddress(mapArgs["/connect"].c_str()));
+ Sleep(10000);
+ }
+
// Initiate network connections
int nTry = 0;
bool fIRCOnly = false;
@@ -740,14 +753,14 @@ void ThreadOpenConnections2(void* parg)
loop
{
// Wait
- vnThreadsRunning[1] = false;
+ vnThreadsRunning[1]--;
Sleep(500);
while (vNodes.size() >= nMaxConnections || vNodes.size() >= mapAddresses.size())
{
CheckForShutdown(1);
Sleep(2000);
}
- vnThreadsRunning[1] = true;
+ vnThreadsRunning[1]++;
CheckForShutdown(1);
@@ -835,43 +848,48 @@ void ThreadOpenConnections2(void* parg)
// Once we've chosen an IP, we'll try every given port before moving on
foreach(const CAddress& addrConnect, (*mi).second)
- {
- //
- // Initiate outbound network connection
- //
- CheckForShutdown(1);
- if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
- continue;
+ if (OpenNetworkConnection(addrConnect))
+ break;
+ }
+}
- vnThreadsRunning[1] = false;
- CNode* pnode = ConnectNode(addrConnect);
- vnThreadsRunning[1] = true;
- CheckForShutdown(1);
- if (!pnode)
- continue;
- pnode->fNetworkNode = true;
+bool OpenNetworkConnection(const CAddress& addrConnect)
+{
+ //
+ // Initiate outbound network connection
+ //
+ CheckForShutdown(1);
+ if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
+ return false;
- if (addrLocalHost.IsRoutable())
- {
- // Advertise our address
- vector<CAddress> vAddrToSend;
- vAddrToSend.push_back(addrLocalHost);
- pnode->PushMessage("addr", vAddrToSend);
- }
+ vnThreadsRunning[1]--;
+ CNode* pnode = ConnectNode(addrConnect);
+ vnThreadsRunning[1]++;
+ CheckForShutdown(1);
+ if (!pnode)
+ return false;
+ pnode->fNetworkNode = true;
- // Get as many addresses as we can
- pnode->PushMessage("getaddr");
+ if (addrLocalHost.IsRoutable() && !fUseProxy)
+ {
+ // Advertise our address
+ vector<CAddress> vAddrToSend;
+ vAddrToSend.push_back(addrLocalHost);
+ pnode->PushMessage("addr", vAddrToSend);
+ }
- ////// should the one on the receiving end do this too?
- // Subscribe our local subscription list
- const unsigned int nHops = 0;
- for (unsigned int nChannel = 0; nChannel < pnodeLocalHost->vfSubscribe.size(); nChannel++)
- if (pnodeLocalHost->vfSubscribe[nChannel])
- pnode->PushMessage("subscribe", nChannel, nHops);
+ // Get as many addresses as we can
+ pnode->PushMessage("getaddr");
+ pnode->fGetAddr = true; // don't relay the results of the getaddr
- break;
- }
- }
+ ////// should the one on the receiving end do this too?
+ // Subscribe our local subscription list
+ const unsigned int nHops = 0;
+ for (unsigned int nChannel = 0; nChannel < pnodeLocalHost->vfSubscribe.size(); nChannel++)
+ if (pnodeLocalHost->vfSubscribe[nChannel])
+ pnode->PushMessage("subscribe", nChannel, nHops);
+
+ return true;
}
@@ -887,18 +905,18 @@ void ThreadMessageHandler(void* parg)
loop
{
- vnThreadsRunning[2] = true;
+ vnThreadsRunning[2]++;
CheckForShutdown(2);
try
{
ThreadMessageHandler2(parg);
- vnThreadsRunning[2] = false;
+ vnThreadsRunning[2]--;
}
catch (std::exception& e) {
- vnThreadsRunning[2] = false;
+ vnThreadsRunning[2]--;
PrintException(&e, "ThreadMessageHandler()");
} catch (...) {
- vnThreadsRunning[2] = false;
+ vnThreadsRunning[2]--;
PrintException(NULL, "ThreadMessageHandler()");
}
Sleep(5000);
@@ -931,9 +949,9 @@ void ThreadMessageHandler2(void* parg)
}
// Wait and allow messages to bunch up
- vnThreadsRunning[2] = false;
+ vnThreadsRunning[2]--;
Sleep(100);
- vnThreadsRunning[2] = true;
+ vnThreadsRunning[2]++;
CheckForShutdown(2);
}
}
@@ -982,7 +1000,7 @@ bool StartNode(string& strError)
printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
// Create socket for listening for incoming connections
- SOCKET hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (hListenSocket == INVALID_SOCKET)
{
strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
@@ -1024,13 +1042,21 @@ bool StartNode(string& strError)
}
// Get our external IP address for incoming connections
- if (addrIncoming.ip)
- addrLocalHost.ip = addrIncoming.ip;
-
- if (GetMyExternalIP(addrLocalHost.ip))
+ if (fUseProxy)
{
- addrIncoming = addrLocalHost;
- CWalletDB().WriteSetting("addrIncoming", addrIncoming);
+ // Proxies can't take incoming connections
+ addrLocalHost.ip = CAddress("0.0.0.0").ip;
+ }
+ else
+ {
+ if (addrIncoming.ip)
+ addrLocalHost.ip = addrIncoming.ip;
+
+ if (GetMyExternalIP(addrLocalHost.ip))
+ {
+ addrIncoming = addrLocalHost;
+ CWalletDB().WriteSetting("addrIncoming", addrIncoming);
+ }
}
// Get addresses from IRC and advertise ours
@@ -1040,7 +1066,7 @@ bool StartNode(string& strError)
//
// Start threads
//
- if (_beginthread(ThreadSocketHandler, 0, new SOCKET(hListenSocket)) == -1)
+ if (_beginthread(ThreadSocketHandler, 0, NULL) == -1)
{
strError = "Error: _beginthread(ThreadSocketHandler) failed";
printf("%s\n", strError.c_str());
@@ -1094,10 +1120,15 @@ void CheckForShutdown(int n)
if (fShutdown)
{
if (n != -1)
- vnThreadsRunning[n] = false;
+ if (--vnThreadsRunning[n] < 0)
+ vnThreadsRunning[n] = 0;
if (n == 0)
+ {
foreach(CNode* pnode, vNodes)
closesocket(pnode->hSocket);
+ closesocket(hListenSocket);
+ }
+ printf("Thread %d exiting\n", n);
_endthread();
}
}
diff --git a/net.h b/net.h
index 334100422f..a0b2929daa 100644
--- a/net.h
+++ b/net.h
@@ -174,7 +174,7 @@ public:
{
nServices = nServicesIn;
memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
- ip = 0;
+ ip = INADDR_NONE;
port = DEFAULT_PORT;
nTime = GetAdjustedTime();
nLastFailed = 0;
@@ -183,7 +183,7 @@ public:
if (strlen(pszIn) > ARRAYLEN(psz)-1)
return;
strcpy(psz, pszIn);
- unsigned int a, b, c, d, e;
+ unsigned int a=0, b=0, c=0, d=0, e=0;
if (sscanf(psz, "%u.%u.%u.%u:%u", &a, &b, &c, &d, &e) < 4)
return;
char* pszPort = strchr(psz, ':');
@@ -191,6 +191,10 @@ public:
{
*pszPort++ = '\0';
port = htons(atoi(pszPort));
+ if (atoi(pszPort) > USHRT_MAX)
+ port = htons(USHRT_MAX);
+ if (atoi(pszPort) < 0)
+ port = htons(0);
}
ip = inet_addr(psz);
}
@@ -215,6 +219,11 @@ public:
a.port == b.port);
}
+ friend inline bool operator!=(const CAddress& a, const CAddress& b)
+ {
+ return (!(a == b));
+ }
+
friend inline bool operator<(const CAddress& a, const CAddress& b)
{
int ret = memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved));
@@ -277,6 +286,11 @@ public:
return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
}
+ string ToStringPort() const
+ {
+ return strprintf("%u", ntohs(port));
+ }
+
string ToStringLog() const
{
return "";
@@ -416,6 +430,7 @@ extern bool fClient;
extern uint64 nLocalServices;
extern CAddress addrLocalHost;
extern CNode* pnodeLocalHost;
+extern uint64 nLocalHostNonce;
extern bool fShutdown;
extern array<int, 10> vnThreadsRunning;
extern vector<CNode*> vNodes;
@@ -426,6 +441,9 @@ extern map<CInv, CDataStream> mapRelay;
extern deque<pair<int64, CInv> > vRelayExpiration;
extern CCriticalSection cs_mapRelay;
extern map<CInv, int64> mapAlreadyAskedFor;
+
+// Settings
+extern int fUseProxy;
extern CAddress addrProxy;
@@ -448,6 +466,7 @@ public:
bool fClient;
bool fInbound;
bool fNetworkNode;
+ bool fSuccessfullyConnected;
bool fDisconnect;
protected:
int nRefCount;
@@ -459,6 +478,7 @@ public:
// flood
vector<CAddress> vAddrToSend;
set<CAddress> setAddrKnown;
+ bool fGetAddr;
// inventory based relay
set<CInv> setInventoryKnown;
@@ -483,15 +503,20 @@ public:
fClient = false; // set by version message
fInbound = fInboundIn;
fNetworkNode = false;
+ fSuccessfullyConnected = false;
fDisconnect = false;
nRefCount = 0;
nReleaseTime = 0;
+ fGetAddr = false;
vfSubscribe.assign(256, false);
// Push a version message
/// when NTP implemented, change to just nTime = GetAdjustedTime()
int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
- PushMessage("version", VERSION, nLocalServices, nTime, addr);
+ CAddress addrYou = (fUseProxy ? CAddress("0.0.0.0") : addr);
+ CAddress addrMe = (fUseProxy ? CAddress("0.0.0.0") : addrLocalHost);
+ RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
+ PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe, nLocalHostNonce);
}
~CNode()
@@ -531,6 +556,21 @@ public:
+ void AddAddressKnown(const CAddress& addr)
+ {
+ setAddrKnown.insert(addr);
+ }
+
+ void PushAddress(const CAddress& addr)
+ {
+ // Known checking here is only to save space from duplicates.
+ // SendMessages will filter it again for knowns that were added
+ // after addresses were pushed.
+ if (!setAddrKnown.count(addr))
+ vAddrToSend.push_back(addr);
+ }
+
+
void AddInventoryKnown(const CInv& inv)
{
CRITICAL_BLOCK(cs_inventory)
@@ -562,7 +602,6 @@ public:
}
-
void BeginMessage(const char* pszCommand)
{
EnterCriticalSection(&cs_vSend);
@@ -570,7 +609,7 @@ public:
AbortMessage();
nPushPos = vSend.size();
vSend << CMessageHeader(pszCommand, 0);
- printf("sending: %-12s ", pszCommand);
+ printf("sending: %s ", pszCommand);
}
void AbortMessage()
@@ -706,6 +745,86 @@ public:
}
}
+ template<typename T1, typename T2, typename T3, typename T4, typename T5>
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ vSend << a1 << a2 << a3 << a4 << a5;
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ vSend << a1 << a2 << a3 << a4 << a5 << a6;
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7;
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8;
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9)
+ {
+ try
+ {
+ BeginMessage(pszCommand);
+ vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9;
+ EndMessage();
+ }
+ catch (...)
+ {
+ AbortMessage();
+ throw;
+ }
+ }
+
void PushRequest(const char* pszCommand,
void (*fn)(void*, CDataStream&), void* param1)
@@ -750,7 +869,7 @@ public:
bool IsSubscribed(unsigned int nChannel);
void Subscribe(unsigned int nChannel, unsigned int nHops=0);
void CancelSubscribe(unsigned int nChannel);
- void Disconnect();
+ void DoDisconnect();
};
diff --git a/serialize.h b/serialize.h
index b7ab86d22a..9b20e2a0f6 100644
--- a/serialize.h
+++ b/serialize.h
@@ -19,7 +19,7 @@ class CScript;
class CDataStream;
class CAutoFile;
-static const int VERSION = 105;
+static const int VERSION = 106;
diff --git a/strlcpy.h b/strlcpy.h
new file mode 100644
index 0000000000..a79ee1756c
--- /dev/null
+++ b/strlcpy.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+inline size_t strlcpy(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0)
+ {
+ while (--n != 0)
+ {
+ if ((*d++ = *s++) == '\0')
+ break;
+ }
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0)
+ {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+inline size_t strlcat(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return(dlen + strlen(s));
+ while (*s != '\0')
+ {
+ if (n != 1)
+ {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src)); /* count does not include NUL */
+}
diff --git a/ui.cpp b/ui.cpp
index 428304796e..917c64b445 100644
--- a/ui.cpp
+++ b/ui.cpp
@@ -497,7 +497,7 @@ string SingleLine(const string& strIn)
return strOut;
}
-void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
+bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
{
int64 nTime = wtx.nTimeDisplayed = wtx.GetTxTime();
int64 nCredit = wtx.GetCredit();
@@ -506,14 +506,11 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
uint256 hash = wtx.GetHash();
string strStatus = FormatTxStatus(wtx);
map<string, string> mapValue = wtx.mapValue;
+ wtx.nLinesDisplayed = 1;
// Filter
if (wtx.IsCoinBase())
{
- // View->Show Generated
- if (!fShowGenerated)
- return;
-
// Don't show generated coin until confirmed by at least one block after it
// so we don't get the user's hopes up until it looks like it's probably accepted.
//
@@ -527,10 +524,13 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
//
if (wtx.GetDepthInMainChain() < 2)
{
- // In case it was previously displayed
- DeleteLine(hash);
- return;
+ wtx.nLinesDisplayed = 0;
+ return false;
}
+
+ // View->Show Generated
+ if (!fShowGenerated)
+ return false;
}
// Find the block the tx is in
@@ -644,6 +644,7 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
// Debit
//
int64 nTxFee = nDebit - wtx.GetValueOut();
+ wtx.nLinesDisplayed = 0;
for (int nOut = 0; nOut < wtx.vout.size(); nOut++)
{
const CTxOut& txout = wtx.vout[nOut];
@@ -685,6 +686,7 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
SingleLine(strDescription),
FormatMoney(-nValue, true),
"");
+ wtx.nLinesDisplayed++;
}
}
else
@@ -706,12 +708,14 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
"");
}
}
+
+ return true;
}
void CMainFrame::RefreshStatus()
{
static int nLastTop;
- int nTop = m_listCtrl->GetTopItem();
+ int nTop = max((int)m_listCtrl->GetTopItem(), 0);
if (nTop == nLastTop && pindexBestLast == pindexBest)
return;
@@ -729,7 +733,7 @@ void CMainFrame::RefreshStatus()
nLastTop = nTop;
pindexBestLast = pindexBest;
- for (int nIndex = nStart; nIndex < nEnd; nIndex++)
+ for (int nIndex = nStart; nIndex < min(nEnd, m_listCtrl->GetItemCount()); nIndex++)
{
uint256 hash((string)GetItemText(m_listCtrl, nIndex, 1));
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
@@ -738,9 +742,12 @@ void CMainFrame::RefreshStatus()
printf("CMainFrame::RefreshStatus() : tx not found in mapWallet\n");
continue;
}
- const CWalletTx& wtx = (*mi).second;
+ CWalletTx& wtx = (*mi).second;
if (wtx.IsCoinBase() || wtx.GetTxTime() != wtx.nTimeDisplayed)
- InsertTransaction(wtx, false, nIndex);
+ {
+ if (!InsertTransaction(wtx, false, nIndex))
+ m_listCtrl->DeleteItem(nIndex--);
+ }
else
m_listCtrl->SetItem(nIndex, 2, FormatTxStatus(wtx));
}
@@ -801,6 +808,9 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
}
printf("RefreshListCtrl done\n");
+
+ // Update transaction total display
+ MainFrameRepaint();
}
else
{
@@ -834,31 +844,54 @@ void DelayedRepaint(void* parg)
return;
fOneThread = true;
Sleep(1000);
+ printf("DelayedRepaint()\n");
MainFrameRepaint();
fOneThread = false;
}
void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
{
+ if (ptaskbaricon)
+ ptaskbaricon->UpdateTooltip();
+
// Update listctrl contents
if (!vWalletUpdated.empty())
{
TRY_CRITICAL_BLOCK(cs_mapWallet)
{
+ bool fInserted = false;
foreach(uint256 hash, vWalletUpdated)
{
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
if (mi != mapWallet.end())
- InsertTransaction((*mi).second, false);
+ fInserted |= InsertTransaction((*mi).second, false);
}
- m_listCtrl->ScrollList(0, INT_MAX);
vWalletUpdated.clear();
+ if (fInserted)
+ m_listCtrl->ScrollList(0, INT_MAX);
}
}
// Update status column of visible items only
RefreshStatus();
+ // Balance total
+ bool fRefreshed = false;
+ static int nTransactionCount;
+ TRY_CRITICAL_BLOCK(cs_mapWallet)
+ {
+ fRefreshed = true;
+ m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " ");
+
+ // Count hidden and multi-line transactions
+ nTransactionCount = 0;
+ for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+ {
+ CWalletTx& wtx = (*it).second;
+ nTransactionCount += wtx.nLinesDisplayed;
+ }
+ }
+
// Update status bar
string strGen = "";
if (fGenerateBitcoins)
@@ -867,17 +900,9 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
strGen = "(not connected)";
m_statusBar->SetStatusText(strGen, 1);
- string strStatus = strprintf(" %d connections %d blocks %d transactions", vNodes.size(), nBestHeight + 1, m_listCtrl->GetItemCount());
+ string strStatus = strprintf(" %d connections %d blocks %d transactions", vNodes.size(), nBestHeight + 1, nTransactionCount);
m_statusBar->SetStatusText(strStatus, 2);
- // Balance total
- bool fRefreshed = false;
- TRY_CRITICAL_BLOCK(cs_mapWallet)
- {
- m_staticTextBalance->SetLabel(FormatMoney(GetBalance()) + " ");
- fRefreshed = true;
- }
-
// mapWallet was locked, try again later
if (!vWalletUpdated.empty() || !fRefreshed)
_beginthread(DelayedRepaint, 0, NULL);
@@ -1350,6 +1375,14 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent)
m_checkBoxMinimizeOnClose->Enable(fMinimizeToTray);
m_checkBoxMinimizeOnClose->SetValue(fMinimizeToTray && fMinimizeOnClose);
fTmpMinimizeOnClose = fMinimizeOnClose;
+ m_checkBoxUseProxy->SetValue(fUseProxy);
+ m_textCtrlProxyIP->Enable(fUseProxy);
+ m_textCtrlProxyPort->Enable(fUseProxy);
+ m_staticTextProxyIP->Enable(fUseProxy);
+ m_staticTextProxyPort->Enable(fUseProxy);
+ m_textCtrlProxyIP->SetValue(addrProxy.ToStringIP());
+ m_textCtrlProxyPort->SetValue(addrProxy.ToStringPort());
+
m_buttonOK->SetFocus();
}
@@ -1395,6 +1428,34 @@ void COptionsDialog::OnCheckBoxMinimizeToTray(wxCommandEvent& event)
}
+void COptionsDialog::OnCheckBoxUseProxy(wxCommandEvent& event)
+{
+ m_textCtrlProxyIP->Enable(event.IsChecked());
+ m_textCtrlProxyPort->Enable(event.IsChecked());
+ m_staticTextProxyIP->Enable(event.IsChecked());
+ m_staticTextProxyPort->Enable(event.IsChecked());
+}
+
+CAddress COptionsDialog::GetProxyAddr()
+{
+ // Be careful about byte order, addr.ip and addr.port are big endian
+ CAddress addr(m_textCtrlProxyIP->GetValue() + ":" + m_textCtrlProxyPort->GetValue());
+ if (addr.ip == INADDR_NONE)
+ addr.ip = addrProxy.ip;
+ int nPort = atoi(m_textCtrlProxyPort->GetValue());
+ addr.port = htons(nPort);
+ if (nPort <= 0 || nPort > USHRT_MAX)
+ addr.port = addrProxy.port;
+ return addr;
+}
+
+void COptionsDialog::OnKillFocusProxy(wxFocusEvent& event)
+{
+ m_textCtrlProxyIP->SetValue(GetProxyAddr().ToStringIP());
+ m_textCtrlProxyPort->SetValue(GetProxyAddr().ToStringPort());
+}
+
+
void COptionsDialog::OnButtonOK(wxCommandEvent& event)
{
OnButtonApply(event);
@@ -1446,6 +1507,18 @@ void COptionsDialog::OnButtonApply(wxCommandEvent& event)
fMinimizeOnClose = (fMinimizeToTray ? m_checkBoxMinimizeOnClose->GetValue() : fTmpMinimizeOnClose);
walletdb.WriteSetting("fMinimizeOnClose", fMinimizeOnClose);
}
+
+ if (fUseProxy != m_checkBoxUseProxy->GetValue())
+ {
+ fUseProxy = m_checkBoxUseProxy->GetValue();
+ walletdb.WriteSetting("fUseProxy", fUseProxy);
+ }
+
+ if (addrProxy != GetProxyAddr())
+ {
+ addrProxy = GetProxyAddr();
+ walletdb.WriteSetting("addrProxy", addrProxy);
+ }
}
@@ -1657,7 +1730,7 @@ CSendingDialog::CSendingDialog(wxWindow* parent, const CAddress& addrIn, int64 n
nPrice = nPriceIn;
wtx = wtxIn;
start = wxDateTime::UNow();
- strStatus = "";
+ memset(pszStatus, 0, sizeof(pszStatus));
fCanCancel = true;
fAbort = false;
fSuccess = false;
@@ -1721,10 +1794,10 @@ void CSendingDialog::OnButtonCancel(wxCommandEvent& event)
void CSendingDialog::OnPaint(wxPaintEvent& event)
{
- if (strStatus.size() > 130)
- m_textCtrlStatus->SetValue(string("\n") + strStatus);
+ if (strlen(pszStatus) > 130)
+ m_textCtrlStatus->SetValue(string("\n") + pszStatus);
else
- m_textCtrlStatus->SetValue(string("\n\n") + strStatus);
+ m_textCtrlStatus->SetValue(string("\n\n") + pszStatus);
m_staticTextSending->SetFocus();
if (!fCanCancel)
m_buttonCancel->Enable(false);
@@ -1736,7 +1809,7 @@ void CSendingDialog::OnPaint(wxPaintEvent& event)
}
if (fAbort && fCanCancel && IsShown())
{
- strStatus = "CANCELLED";
+ strcpy(pszStatus, "CANCELLED");
m_buttonOK->Enable(true);
m_buttonOK->SetFocus();
m_buttonCancel->Enable(false);
@@ -1777,7 +1850,8 @@ bool CSendingDialog::Status()
}
if (fAbort && fCanCancel)
{
- strStatus = "CANCELLED";
+ memset(pszStatus, 0, 10);
+ strcpy(pszStatus, "CANCELLED");
Repaint();
fWorkDone = true;
return false;
@@ -1789,7 +1863,12 @@ bool CSendingDialog::Status(const string& str)
{
if (!Status())
return false;
- strStatus = str;
+
+ // This can be read by the UI thread at any time,
+ // so copy in a way that can be read cleanly at all times.
+ memset(pszStatus, 0, min(str.size()+1, sizeof(pszStatus)));
+ strlcpy(pszStatus, str.c_str(), sizeof(pszStatus));
+
Repaint();
return true;
}
@@ -1950,8 +2029,8 @@ void CSendingDialog::OnReply3(CDataStream& vRecv)
if (nRet > 0)
{
Error("The payment was sent, but the recipient was unable to verify it.\n"
- "The transaction is recorded and will credit to the recipient if it is valid,\n"
- "but without comment information.");
+ "The transaction is recorded and will credit to the recipient,\n"
+ "but the comment information will be blank.");
return;
}
}
@@ -3092,6 +3171,7 @@ END_EVENT_TABLE()
void CMyTaskBarIcon::Show(bool fShow)
{
+ static char pszPrevTip[200];
if (fShow)
{
string strTooltip = "Bitcoin";
@@ -3099,10 +3179,17 @@ void CMyTaskBarIcon::Show(bool fShow)
strTooltip = "Bitcoin - Generating";
if (fGenerateBitcoins && vNodes.empty())
strTooltip = "Bitcoin - (not connected)";
- SetIcon(wxICON(bitcoin), strTooltip);
+
+ // Optimization, only update when changed, using char array to be reentrant
+ if (strncmp(pszPrevTip, strTooltip.c_str(), sizeof(pszPrevTip)-1) != 0)
+ {
+ strlcpy(pszPrevTip, strTooltip.c_str(), sizeof(pszPrevTip));
+ SetIcon(wxICON(bitcoin), strTooltip);
+ }
}
else
{
+ strlcpy(pszPrevTip, "", sizeof(pszPrevTip));
RemoveIcon();
}
}
@@ -3301,12 +3388,12 @@ bool CMyApp::OnInit2()
if (mapArgs.count("/datadir"))
strSetDataDir = mapArgs["/datadir"];
- if (mapArgs.count("/proxy"))
- addrProxy = CAddress(mapArgs["/proxy"].c_str());
-
if (mapArgs.count("/debug"))
fDebug = true;
+ if (mapArgs.count("/printtodebugger"))
+ fPrintToDebugger = true;
+
if (mapArgs.count("/dropmessages"))
{
nDropMessagesTest = atoi(mapArgs["/dropmessages"]);
@@ -3380,6 +3467,20 @@ bool CMyApp::OnInit2()
return false;
}
+ if (mapArgs.count("/proxy"))
+ {
+ fUseProxy = true;
+ addrProxy = CAddress(mapArgs["/proxy"].c_str());
+ if (addrProxy.ip == INADDR_NONE)
+ {
+ wxMessageBox("Invalid /proxy address", "Bitcoin");
+ OnExit();
+ }
+ CWalletDB walletdb;
+ walletdb.WriteSetting("fUseProxy", fUseProxy);
+ walletdb.WriteSetting("addrProxy", addrProxy);
+ }
+
if (mapArgs.count("/gen"))
{
if (mapArgs["/gen"].empty())
@@ -3404,7 +3505,7 @@ bool CMyApp::OnInit2()
return false;
}
- //RandAddSeedPerfmon();
+ RandAddSeedPerfmon();
if (!StartNode(strErrors))
wxMessageBox(strErrors, "Bitcoin");
@@ -3514,7 +3615,7 @@ void CMyApp::OnFatalException()
void MainFrameRepaint()
{
- // This is called by network code that shouldn't access pframeMain and ptaskbaricon
+ // This is called by network code that shouldn't access pframeMain
// directly because it could still be running after the UI is closed.
if (pframeMain)
{
@@ -3523,20 +3624,47 @@ void MainFrameRepaint()
pframeMain->Refresh();
pframeMain->AddPendingEvent(event);
}
- if (ptaskbaricon)
- ptaskbaricon->UpdateTooltip();
}
+typedef WINSHELLAPI BOOL WINAPI (*PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
+
+string MyGetSpecialFolderPath(int nFolder, bool fCreate)
+{
+ char pszPath[MAX_PATH+100] = "";
+
+ // SHGetSpecialFolderPath is not usually available on NT 4.0
+ HMODULE hShell32 = LoadLibrary("shell32.dll");
+ if (hShell32)
+ {
+ PSHGETSPECIALFOLDERPATHA pSHGetSpecialFolderPath =
+ (PSHGETSPECIALFOLDERPATHA)GetProcAddress(hShell32, "SHGetSpecialFolderPathA");
+ if (pSHGetSpecialFolderPath)
+ (*pSHGetSpecialFolderPath)(NULL, pszPath, nFolder, fCreate);
+ FreeModule(hShell32);
+ }
+
+ // Backup option
+ if (pszPath[0] == '\0')
+ {
+ if (nFolder == CSIDL_STARTUP)
+ {
+ strcpy(pszPath, getenv("USERPROFILE"));
+ strcat(pszPath, "\\Start Menu\\Programs\\Startup");
+ }
+ else if (nFolder == CSIDL_APPDATA)
+ {
+ strcpy(pszPath, getenv("APPDATA"));
+ }
+ }
+
+ return pszPath;
+}
+
string StartupShortcutPath()
{
- // Get the startup folder shortcut path
- char pszLinkPath[MAX_PATH+100];
- pszLinkPath[0] = '\0';
- SHGetSpecialFolderPath(0, pszLinkPath, CSIDL_STARTUP, 0);
- strcat(pszLinkPath, "\\Bitcoin.lnk");
- return pszLinkPath;
+ return MyGetSpecialFolderPath(CSIDL_STARTUP, true) + "\\Bitcoin.lnk";
}
bool GetStartOnSystemStartup()
@@ -3630,7 +3758,8 @@ void ThreadRandSendTest(void* parg)
if (GetBalance() < nValue)
{
wxMessageBox("Out of money ");
- return;
+ while (GetBalance() < 1000)
+ Sleep(1000);
}
nValue += (nRep % 100) * CENT;
diff --git a/ui.h b/ui.h
index f451d93565..9fc7e0ebe7 100644
--- a/ui.h
+++ b/ui.h
@@ -89,7 +89,7 @@ public:
void OnCrossThreadCall(wxCommandEvent& event);
void InsertLine(bool fNew, int nIndex, uint256 hashKey, string strSort, const wxString& str1, const wxString& str2, const wxString& str3, const wxString& str4, const wxString& str5);
bool DeleteLine(uint256 hashKey);
- void InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex=-1);
+ bool InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex=-1);
void RefreshListCtrl();
void RefreshStatus();
};
@@ -121,6 +121,9 @@ protected:
void OnKillFocusTransactionFee(wxFocusEvent& event);
void OnCheckBoxLimitProcessors(wxCommandEvent& event);
void OnCheckBoxMinimizeToTray(wxCommandEvent& event);
+ void OnCheckBoxUseProxy(wxCommandEvent& event);
+ void OnKillFocusProxy(wxFocusEvent& event);
+
void OnButtonOK(wxCommandEvent& event);
void OnButtonCancel(wxCommandEvent& event);
void OnButtonApply(wxCommandEvent& event);
@@ -133,6 +136,7 @@ public:
bool fTmpStartOnSystemStartup;
bool fTmpMinimizeOnClose;
void SelectPage(int nPage);
+ CAddress GetProxyAddr();
};
@@ -193,7 +197,7 @@ public:
int64 nPrice;
CWalletTx wtx;
wxDateTime start;
- string strStatus;
+ char pszStatus[10000];
bool fCanCancel;
bool fAbort;
bool fSuccess;
diff --git a/uibase.cpp b/uibase.cpp
index 0f9e22c528..b03e578bd8 100644
--- a/uibase.cpp
+++ b/uibase.cpp
@@ -380,7 +380,7 @@ COptionsDialogBase::COptionsDialogBase( wxWindow* parent, wxWindowID id, const w
bSizer69 = new wxBoxSizer( wxVERTICAL );
- bSizer69->Add( 0, 14, 0, wxEXPAND, 5 );
+ bSizer69->Add( 0, 16, 0, wxEXPAND, 5 );
m_staticText32 = new wxStaticText( m_panelMain, wxID_ANY, wxT("Optional transaction fee you give to the nodes that process your transactions."), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText32->Wrap( -1 );
@@ -412,7 +412,7 @@ COptionsDialogBase::COptionsDialogBase( wxWindow* parent, wxWindowID id, const w
bSizer71->Add( m_checkBoxLimitProcessors, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_spinCtrlLimitProcessors = new wxSpinCtrl( m_panelMain, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 48,-1 ), wxSP_ARROW_KEYS, 1, 999, 1 );
- bSizer71->Add( m_spinCtrlLimitProcessors, 0, wxTOP|wxBOTTOM, 5 );
+ bSizer71->Add( m_spinCtrlLimitProcessors, 0, wxALIGN_CENTER_VERTICAL, 5 );
m_staticText35 = new wxStaticText( m_panelMain, wxID_ANY, wxT("processors"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText35->Wrap( -1 );
@@ -434,12 +434,45 @@ COptionsDialogBase::COptionsDialogBase( wxWindow* parent, wxWindowID id, const w
bSizer101->Add( 16, 0, 0, 0, 5 );
- m_checkBoxMinimizeOnClose = new wxCheckBox( m_panelMain, wxID_ANY, wxT("M&inimize to system tray on close"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_checkBoxMinimizeOnClose = new wxCheckBox( m_panelMain, wxID_ANY, wxT("Mi&nimize to system tray on close"), wxDefaultPosition, wxDefaultSize, 0 );
- bSizer101->Add( m_checkBoxMinimizeOnClose, 0, wxALL, 5 );
+ bSizer101->Add( m_checkBoxMinimizeOnClose, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
bSizer69->Add( bSizer101, 1, wxEXPAND, 5 );
+ wxBoxSizer* bSizer102;
+ bSizer102 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_checkBoxUseProxy = new wxCheckBox( m_panelMain, wxID_ANY, wxT("&Connect through socks4 proxy: "), wxDefaultPosition, wxDefaultSize, 0 );
+
+ bSizer102->Add( m_checkBoxUseProxy, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ bSizer69->Add( bSizer102, 1, wxEXPAND, 5 );
+
+ wxBoxSizer* bSizer103;
+ bSizer103 = new wxBoxSizer( wxHORIZONTAL );
+
+
+ bSizer103->Add( 18, 0, 0, 0, 5 );
+
+ m_staticTextProxyIP = new wxStaticText( m_panelMain, wxID_ANY, wxT("Proxy &IP:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextProxyIP->Wrap( -1 );
+ bSizer103->Add( m_staticTextProxyIP, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_textCtrlProxyIP = new wxTextCtrl( m_panelMain, wxID_PROXYIP, wxEmptyString, wxDefaultPosition, wxSize( 140,-1 ), 0 );
+ m_textCtrlProxyIP->SetMaxLength( 15 );
+ bSizer103->Add( m_textCtrlProxyIP, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_staticTextProxyPort = new wxStaticText( m_panelMain, wxID_ANY, wxT(" &Port:"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextProxyPort->Wrap( -1 );
+ bSizer103->Add( m_staticTextProxyPort, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
+
+ m_textCtrlProxyPort = new wxTextCtrl( m_panelMain, wxID_PROXYPORT, wxEmptyString, wxDefaultPosition, wxSize( 55,-1 ), 0 );
+ m_textCtrlProxyPort->SetMaxLength( 5 );
+ bSizer103->Add( m_textCtrlProxyPort, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+ bSizer69->Add( bSizer103, 1, wxEXPAND, 5 );
+
m_panelMain->SetSizer( bSizer69 );
m_panelMain->Layout();
bSizer69->Fit( m_panelMain );
@@ -450,13 +483,13 @@ COptionsDialogBase::COptionsDialogBase( wxWindow* parent, wxWindowID id, const w
bSizer64 = new wxBoxSizer( wxVERTICAL );
- bSizer64->Add( 0, 14, 0, wxEXPAND, 5 );
+ bSizer64->Add( 0, 16, 0, wxEXPAND, 5 );
m_staticText321 = new wxStaticText( m_panelTest2, wxID_ANY, wxT("Test panel 2 for future expansion"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText321->Wrap( -1 );
bSizer64->Add( m_staticText321, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
- m_staticText69 = new wxStaticText( m_panelTest2, wxID_ANY, wxT("MyLabel"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticText69 = new wxStaticText( m_panelTest2, wxID_ANY, wxT("Let's not start multiple pages until the first page is filled up"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText69->Wrap( -1 );
bSizer64->Add( m_staticText69, 0, wxALL, 5 );
@@ -506,6 +539,9 @@ COptionsDialogBase::COptionsDialogBase( wxWindow* parent, wxWindowID id, const w
m_textCtrlTransactionFee->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( COptionsDialogBase::OnKillFocusTransactionFee ), NULL, this );
m_checkBoxLimitProcessors->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnCheckBoxLimitProcessors ), NULL, this );
m_checkBoxMinimizeToTray->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnCheckBoxMinimizeToTray ), NULL, this );
+ m_checkBoxUseProxy->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnCheckBoxUseProxy ), NULL, this );
+ m_textCtrlProxyIP->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( COptionsDialogBase::OnKillFocusProxy ), NULL, this );
+ m_textCtrlProxyPort->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( COptionsDialogBase::OnKillFocusProxy ), NULL, this );
m_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnButtonOK ), NULL, this );
m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnButtonCancel ), NULL, this );
m_buttonApply->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnButtonApply ), NULL, this );
@@ -518,6 +554,9 @@ COptionsDialogBase::~COptionsDialogBase()
m_textCtrlTransactionFee->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( COptionsDialogBase::OnKillFocusTransactionFee ), NULL, this );
m_checkBoxLimitProcessors->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnCheckBoxLimitProcessors ), NULL, this );
m_checkBoxMinimizeToTray->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnCheckBoxMinimizeToTray ), NULL, this );
+ m_checkBoxUseProxy->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnCheckBoxUseProxy ), NULL, this );
+ m_textCtrlProxyIP->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( COptionsDialogBase::OnKillFocusProxy ), NULL, this );
+ m_textCtrlProxyPort->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( COptionsDialogBase::OnKillFocusProxy ), NULL, this );
m_buttonOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnButtonOK ), NULL, this );
m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnButtonCancel ), NULL, this );
m_buttonApply->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnButtonApply ), NULL, this );
diff --git a/uibase.h b/uibase.h
index e262a3dcb6..d52158f127 100644
--- a/uibase.h
+++ b/uibase.h
@@ -50,50 +50,52 @@
#define wxID_BUTTONCOPY 1006
#define wxID_BUTTONCHANGE 1007
#define wxID_TRANSACTIONFEE 1008
-#define wxID_TEXTCTRLPAYTO 1009
-#define wxID_BUTTONPASTE 1010
-#define wxID_BUTTONADDRESSBOOK 1011
-#define wxID_TEXTCTRLAMOUNT 1012
-#define wxID_CHOICETRANSFERTYPE 1013
-#define wxID_LISTCTRL 1014
-#define wxID_BUTTONRENAME 1015
-#define wxID_BUTTONNEW 1016
-#define wxID_BUTTONEDIT 1017
-#define wxID_BUTTONDELETE 1018
-#define wxID_DEL0 1019
-#define wxID_DEL1 1020
-#define wxID_DEL2 1021
-#define wxID_DEL3 1022
-#define wxID_DEL4 1023
-#define wxID_DEL5 1024
-#define wxID_DEL6 1025
-#define wxID_DEL7 1026
-#define wxID_DEL8 1027
-#define wxID_DEL9 1028
-#define wxID_DEL10 1029
-#define wxID_DEL11 1030
-#define wxID_DEL12 1031
-#define wxID_DEL13 1032
-#define wxID_DEL14 1033
-#define wxID_DEL15 1034
-#define wxID_DEL16 1035
-#define wxID_DEL17 1036
-#define wxID_DEL18 1037
-#define wxID_DEL19 1038
-#define wxID_BUTTONPREVIEW 1039
-#define wxID_BUTTONSAMPLE 1040
-#define wxID_CANCEL2 1041
-#define wxID_BUTTONBACK 1042
-#define wxID_BUTTONNEXT 1043
-#define wxID_SUBMIT 1044
-#define wxID_OPENNEWTABLE 1045
-#define wxID_DEALHAND 1046
-#define wxID_FOLD 1047
-#define wxID_CALL 1048
-#define wxID_RAISE 1049
-#define wxID_LEAVETABLE 1050
-#define wxID_DITCHPLAYER 1051
-#define wxID_TEXTCTRL 1052
+#define wxID_PROXYIP 1009
+#define wxID_PROXYPORT 1010
+#define wxID_TEXTCTRLPAYTO 1011
+#define wxID_BUTTONPASTE 1012
+#define wxID_BUTTONADDRESSBOOK 1013
+#define wxID_TEXTCTRLAMOUNT 1014
+#define wxID_CHOICETRANSFERTYPE 1015
+#define wxID_LISTCTRL 1016
+#define wxID_BUTTONRENAME 1017
+#define wxID_BUTTONNEW 1018
+#define wxID_BUTTONEDIT 1019
+#define wxID_BUTTONDELETE 1020
+#define wxID_DEL0 1021
+#define wxID_DEL1 1022
+#define wxID_DEL2 1023
+#define wxID_DEL3 1024
+#define wxID_DEL4 1025
+#define wxID_DEL5 1026
+#define wxID_DEL6 1027
+#define wxID_DEL7 1028
+#define wxID_DEL8 1029
+#define wxID_DEL9 1030
+#define wxID_DEL10 1031
+#define wxID_DEL11 1032
+#define wxID_DEL12 1033
+#define wxID_DEL13 1034
+#define wxID_DEL14 1035
+#define wxID_DEL15 1036
+#define wxID_DEL16 1037
+#define wxID_DEL17 1038
+#define wxID_DEL18 1039
+#define wxID_DEL19 1040
+#define wxID_BUTTONPREVIEW 1041
+#define wxID_BUTTONSAMPLE 1042
+#define wxID_CANCEL2 1043
+#define wxID_BUTTONBACK 1044
+#define wxID_BUTTONNEXT 1045
+#define wxID_SUBMIT 1046
+#define wxID_OPENNEWTABLE 1047
+#define wxID_DEALHAND 1048
+#define wxID_FOLD 1049
+#define wxID_CALL 1050
+#define wxID_RAISE 1051
+#define wxID_LEAVETABLE 1052
+#define wxID_DITCHPLAYER 1053
+#define wxID_TEXTCTRL 1054
///////////////////////////////////////////////////////////////////////////////
/// Class CMainFrameBase
@@ -211,6 +213,12 @@ class COptionsDialogBase : public wxDialog
wxCheckBox* m_checkBoxMinimizeToTray;
wxCheckBox* m_checkBoxMinimizeOnClose;
+ wxCheckBox* m_checkBoxUseProxy;
+
+ wxStaticText* m_staticTextProxyIP;
+ wxTextCtrl* m_textCtrlProxyIP;
+ wxStaticText* m_staticTextProxyPort;
+ wxTextCtrl* m_textCtrlProxyPort;
wxPanel* m_panelTest2;
wxStaticText* m_staticText321;
@@ -226,6 +234,8 @@ class COptionsDialogBase : public wxDialog
virtual void OnKillFocusTransactionFee( wxFocusEvent& event ){ event.Skip(); }
virtual void OnCheckBoxLimitProcessors( wxCommandEvent& event ){ event.Skip(); }
virtual void OnCheckBoxMinimizeToTray( wxCommandEvent& event ){ event.Skip(); }
+ virtual void OnCheckBoxUseProxy( wxCommandEvent& event ){ event.Skip(); }
+ virtual void OnKillFocusProxy( wxFocusEvent& event ){ event.Skip(); }
virtual void OnButtonOK( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonCancel( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonApply( wxCommandEvent& event ){ event.Skip(); }
diff --git a/uiproject.fbp b/uiproject.fbp
index af5876b4ab..313e5aa6cc 100644
--- a/uiproject.fbp
+++ b/uiproject.fbp
@@ -1912,7 +1912,7 @@
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="spacer" expanded="1">
- <property name="height">14</property>
+ <property name="height">16</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
@@ -2148,7 +2148,7 @@
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
- <property name="flag">wxTOP|wxBOTTOM</property>
+ <property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property>
<object class="wxSpinCtrl" expanded="1">
<property name="bg"></property>
@@ -2379,7 +2379,7 @@
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
- <property name="flag">wxALL</property>
+ <property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<property name="bg"></property>
@@ -2390,7 +2390,7 @@
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
- <property name="label">M&amp;inimize to system tray on close</property>
+ <property name="label">Mi&amp;nimize to system tray on close</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">m_checkBoxMinimizeOnClose</property>
@@ -2431,6 +2431,302 @@
</object>
</object>
</object>
+ <object class="sizeritem" expanded="1">
+ <property name="border">5</property>
+ <property name="flag">wxEXPAND</property>
+ <property name="proportion">1</property>
+ <object class="wxBoxSizer" expanded="1">
+ <property name="minimum_size"></property>
+ <property name="name">bSizer102</property>
+ <property name="orient">wxHORIZONTAL</property>
+ <property name="permission">none</property>
+ <object class="sizeritem" expanded="1">
+ <property name="border">5</property>
+ <property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>
+ <property name="proportion">0</property>
+ <object class="wxCheckBox" expanded="1">
+ <property name="bg"></property>
+ <property name="checked">0</property>
+ <property name="context_help"></property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="font"></property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="label">&amp;Connect through socks4 proxy: </property>
+ <property name="maximum_size"></property>
+ <property name="minimum_size"></property>
+ <property name="name">m_checkBoxUseProxy</property>
+ <property name="permission">protected</property>
+ <property name="pos"></property>
+ <property name="size"></property>
+ <property name="style"></property>
+ <property name="subclass"></property>
+ <property name="tooltip"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <event name="OnChar"></event>
+ <event name="OnCheckBox">OnCheckBoxUseProxy</event>
+ <event name="OnEnterWindow"></event>
+ <event name="OnEraseBackground"></event>
+ <event name="OnKeyDown"></event>
+ <event name="OnKeyUp"></event>
+ <event name="OnKillFocus"></event>
+ <event name="OnLeaveWindow"></event>
+ <event name="OnLeftDClick"></event>
+ <event name="OnLeftDown"></event>
+ <event name="OnLeftUp"></event>
+ <event name="OnMiddleDClick"></event>
+ <event name="OnMiddleDown"></event>
+ <event name="OnMiddleUp"></event>
+ <event name="OnMotion"></event>
+ <event name="OnMouseEvents"></event>
+ <event name="OnMouseWheel"></event>
+ <event name="OnPaint"></event>
+ <event name="OnRightDClick"></event>
+ <event name="OnRightDown"></event>
+ <event name="OnRightUp"></event>
+ <event name="OnSetFocus"></event>
+ <event name="OnSize"></event>
+ <event name="OnUpdateUI"></event>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem" expanded="1">
+ <property name="border">5</property>
+ <property name="flag">wxEXPAND</property>
+ <property name="proportion">1</property>
+ <object class="wxBoxSizer" expanded="1">
+ <property name="minimum_size"></property>
+ <property name="name">bSizer103</property>
+ <property name="orient">wxHORIZONTAL</property>
+ <property name="permission">none</property>
+ <object class="sizeritem" expanded="1">
+ <property name="border">5</property>
+ <property name="flag"></property>
+ <property name="proportion">0</property>
+ <object class="spacer" expanded="1">
+ <property name="height">0</property>
+ <property name="permission">protected</property>
+ <property name="width">18</property>
+ </object>
+ </object>
+ <object class="sizeritem" expanded="1">
+ <property name="border">5</property>
+ <property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>
+ <property name="proportion">0</property>
+ <object class="wxStaticText" expanded="1">
+ <property name="bg"></property>
+ <property name="context_help"></property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="font"></property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="label">Proxy &amp;IP:</property>
+ <property name="maximum_size"></property>
+ <property name="minimum_size"></property>
+ <property name="name">m_staticTextProxyIP</property>
+ <property name="permission">protected</property>
+ <property name="pos"></property>
+ <property name="size"></property>
+ <property name="style"></property>
+ <property name="subclass"></property>
+ <property name="tooltip"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <property name="wrap">-1</property>
+ <event name="OnChar"></event>
+ <event name="OnEnterWindow"></event>
+ <event name="OnEraseBackground"></event>
+ <event name="OnKeyDown"></event>
+ <event name="OnKeyUp"></event>
+ <event name="OnKillFocus"></event>
+ <event name="OnLeaveWindow"></event>
+ <event name="OnLeftDClick"></event>
+ <event name="OnLeftDown"></event>
+ <event name="OnLeftUp"></event>
+ <event name="OnMiddleDClick"></event>
+ <event name="OnMiddleDown"></event>
+ <event name="OnMiddleUp"></event>
+ <event name="OnMotion"></event>
+ <event name="OnMouseEvents"></event>
+ <event name="OnMouseWheel"></event>
+ <event name="OnPaint"></event>
+ <event name="OnRightDClick"></event>
+ <event name="OnRightDown"></event>
+ <event name="OnRightUp"></event>
+ <event name="OnSetFocus"></event>
+ <event name="OnSize"></event>
+ <event name="OnUpdateUI"></event>
+ </object>
+ </object>
+ <object class="sizeritem" expanded="1">
+ <property name="border">5</property>
+ <property name="flag">wxALIGN_CENTER_VERTICAL</property>
+ <property name="proportion">0</property>
+ <object class="wxTextCtrl" expanded="1">
+ <property name="bg"></property>
+ <property name="context_help"></property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="font"></property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_PROXYIP</property>
+ <property name="maximum_size"></property>
+ <property name="maxlength">15</property>
+ <property name="minimum_size"></property>
+ <property name="name">m_textCtrlProxyIP</property>
+ <property name="permission">protected</property>
+ <property name="pos"></property>
+ <property name="size">140,-1</property>
+ <property name="style"></property>
+ <property name="subclass"></property>
+ <property name="tooltip"></property>
+ <property name="value"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <event name="OnChar"></event>
+ <event name="OnEnterWindow"></event>
+ <event name="OnEraseBackground"></event>
+ <event name="OnKeyDown"></event>
+ <event name="OnKeyUp"></event>
+ <event name="OnKillFocus">OnKillFocusProxy</event>
+ <event name="OnLeaveWindow"></event>
+ <event name="OnLeftDClick"></event>
+ <event name="OnLeftDown"></event>
+ <event name="OnLeftUp"></event>
+ <event name="OnMiddleDClick"></event>
+ <event name="OnMiddleDown"></event>
+ <event name="OnMiddleUp"></event>
+ <event name="OnMotion"></event>
+ <event name="OnMouseEvents"></event>
+ <event name="OnMouseWheel"></event>
+ <event name="OnPaint"></event>
+ <event name="OnRightDClick"></event>
+ <event name="OnRightDown"></event>
+ <event name="OnRightUp"></event>
+ <event name="OnSetFocus"></event>
+ <event name="OnSize"></event>
+ <event name="OnText"></event>
+ <event name="OnTextEnter"></event>
+ <event name="OnTextMaxLen"></event>
+ <event name="OnTextURL"></event>
+ <event name="OnUpdateUI"></event>
+ </object>
+ </object>
+ <object class="sizeritem" expanded="1">
+ <property name="border">5</property>
+ <property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>
+ <property name="proportion">0</property>
+ <object class="wxStaticText" expanded="1">
+ <property name="bg"></property>
+ <property name="context_help"></property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="font"></property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_ANY</property>
+ <property name="label"> &amp;Port:</property>
+ <property name="maximum_size"></property>
+ <property name="minimum_size"></property>
+ <property name="name">m_staticTextProxyPort</property>
+ <property name="permission">protected</property>
+ <property name="pos"></property>
+ <property name="size"></property>
+ <property name="style"></property>
+ <property name="subclass"></property>
+ <property name="tooltip"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <property name="wrap">-1</property>
+ <event name="OnChar"></event>
+ <event name="OnEnterWindow"></event>
+ <event name="OnEraseBackground"></event>
+ <event name="OnKeyDown"></event>
+ <event name="OnKeyUp"></event>
+ <event name="OnKillFocus"></event>
+ <event name="OnLeaveWindow"></event>
+ <event name="OnLeftDClick"></event>
+ <event name="OnLeftDown"></event>
+ <event name="OnLeftUp"></event>
+ <event name="OnMiddleDClick"></event>
+ <event name="OnMiddleDown"></event>
+ <event name="OnMiddleUp"></event>
+ <event name="OnMotion"></event>
+ <event name="OnMouseEvents"></event>
+ <event name="OnMouseWheel"></event>
+ <event name="OnPaint"></event>
+ <event name="OnRightDClick"></event>
+ <event name="OnRightDown"></event>
+ <event name="OnRightUp"></event>
+ <event name="OnSetFocus"></event>
+ <event name="OnSize"></event>
+ <event name="OnUpdateUI"></event>
+ </object>
+ </object>
+ <object class="sizeritem" expanded="1">
+ <property name="border">5</property>
+ <property name="flag">wxALIGN_CENTER_VERTICAL</property>
+ <property name="proportion">0</property>
+ <object class="wxTextCtrl" expanded="1">
+ <property name="bg"></property>
+ <property name="context_help"></property>
+ <property name="enabled">1</property>
+ <property name="fg"></property>
+ <property name="font"></property>
+ <property name="hidden">0</property>
+ <property name="id">wxID_PROXYPORT</property>
+ <property name="maximum_size"></property>
+ <property name="maxlength">5</property>
+ <property name="minimum_size"></property>
+ <property name="name">m_textCtrlProxyPort</property>
+ <property name="permission">protected</property>
+ <property name="pos"></property>
+ <property name="size">55,-1</property>
+ <property name="style"></property>
+ <property name="subclass"></property>
+ <property name="tooltip"></property>
+ <property name="value"></property>
+ <property name="window_extra_style"></property>
+ <property name="window_name"></property>
+ <property name="window_style"></property>
+ <event name="OnChar"></event>
+ <event name="OnEnterWindow"></event>
+ <event name="OnEraseBackground"></event>
+ <event name="OnKeyDown"></event>
+ <event name="OnKeyUp"></event>
+ <event name="OnKillFocus">OnKillFocusProxy</event>
+ <event name="OnLeaveWindow"></event>
+ <event name="OnLeftDClick"></event>
+ <event name="OnLeftDown"></event>
+ <event name="OnLeftUp"></event>
+ <event name="OnMiddleDClick"></event>
+ <event name="OnMiddleDown"></event>
+ <event name="OnMiddleUp"></event>
+ <event name="OnMotion"></event>
+ <event name="OnMouseEvents"></event>
+ <event name="OnMouseWheel"></event>
+ <event name="OnPaint"></event>
+ <event name="OnRightDClick"></event>
+ <event name="OnRightDown"></event>
+ <event name="OnRightUp"></event>
+ <event name="OnSetFocus"></event>
+ <event name="OnSize"></event>
+ <event name="OnText"></event>
+ <event name="OnTextEnter"></event>
+ <event name="OnTextMaxLen"></event>
+ <event name="OnTextURL"></event>
+ <event name="OnUpdateUI"></event>
+ </object>
+ </object>
+ </object>
+ </object>
</object>
</object>
</object>
@@ -2490,7 +2786,7 @@
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="spacer" expanded="1">
- <property name="height">14</property>
+ <property name="height">16</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
@@ -2558,7 +2854,7 @@
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
- <property name="label">MyLabel</property>
+ <property name="label">Let&apos;s not start multiple pages until the first page is filled up</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">m_staticText69</property>
diff --git a/util.cpp b/util.cpp
index 8271474eee..6ba84a516d 100644
--- a/util.cpp
+++ b/util.cpp
@@ -5,8 +5,9 @@
#include "headers.h"
-
bool fDebug = false;
+bool fPrintToDebugger = false;
+bool fPrintToConsole = false;
@@ -37,8 +38,8 @@ public:
// Seed random number generator with screen scrape and other hardware sources
RAND_screen();
- // Seed random number generator with perfmon data
- RandAddSeed(true);
+ // Seed random number generator with performance counter
+ RandAddSeed();
}
~CInit()
{
@@ -54,40 +55,43 @@ instance_of_cinit;
-void RandAddSeed(bool fPerfmon)
+void RandAddSeed()
{
// Seed with CPU performance counter
LARGE_INTEGER PerformanceCount;
QueryPerformanceCounter(&PerformanceCount);
RAND_add(&PerformanceCount, sizeof(PerformanceCount), 1.5);
memset(&PerformanceCount, 0, sizeof(PerformanceCount));
+}
+void RandAddSeedPerfmon()
+{
+ // This can take up to 2 seconds, so only do it every 10 minutes
static int64 nLastPerfmon;
- if (fPerfmon || GetTime() > nLastPerfmon + 5 * 60)
+ if (GetTime() < nLastPerfmon + 10 * 60)
+ return;
+ nLastPerfmon = GetTime();
+
+ // Seed with the entire set of perfmon data
+ unsigned char pdata[250000];
+ memset(pdata, 0, sizeof(pdata));
+ unsigned long nSize = sizeof(pdata);
+ long ret = RegQueryValueEx(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
+ RegCloseKey(HKEY_PERFORMANCE_DATA);
+ if (ret == ERROR_SUCCESS)
{
- nLastPerfmon = GetTime();
-
- // Seed with the entire set of perfmon data
- unsigned char pdata[250000];
- memset(pdata, 0, sizeof(pdata));
- unsigned long nSize = sizeof(pdata);
- long ret = RegQueryValueEx(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
- RegCloseKey(HKEY_PERFORMANCE_DATA);
- if (ret == ERROR_SUCCESS)
- {
- uint256 hash;
- SHA256(pdata, nSize, (unsigned char*)&hash);
- RAND_add(&hash, sizeof(hash), min(nSize/500.0, (double)sizeof(hash)));
- hash = 0;
- memset(pdata, 0, nSize);
-
- time_t nTime;
- time(&nTime);
- struct tm* ptmTime = gmtime(&nTime);
- char pszTime[200];
- strftime(pszTime, sizeof(pszTime), "%x %H:%M:%S", ptmTime);
- printf("%s RandAddSeed() %d bytes\n", pszTime, nSize);
- }
+ uint256 hash;
+ SHA256(pdata, nSize, (unsigned char*)&hash);
+ RAND_add(&hash, sizeof(hash), min(nSize/500.0, (double)sizeof(hash)));
+ hash = 0;
+ memset(pdata, 0, nSize);
+
+ time_t nTime;
+ time(&nTime);
+ struct tm* ptmTime = gmtime(&nTime);
+ char pszTime[200];
+ strftime(pszTime, sizeof(pszTime), "%x %H:%M:%S", ptmTime);
+ printf("%s RandAddSeed() %d bytes\n", pszTime, nSize);
}
}
@@ -99,7 +103,6 @@ void RandAddSeed(bool fPerfmon)
-
// Safer snprintf
// - prints up to limit-1 characters
// - output string is always null terminated even if limit reached
@@ -172,27 +175,6 @@ bool error(const char* format, ...)
}
-void PrintException(std::exception* pex, const char* pszThread)
-{
- char pszModule[MAX_PATH];
- pszModule[0] = '\0';
- GetModuleFileName(NULL, pszModule, sizeof(pszModule));
- _strlwr(pszModule);
- char pszMessage[1000];
- if (pex)
- snprintf(pszMessage, sizeof(pszMessage),
- "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
- else
- snprintf(pszMessage, sizeof(pszMessage),
- "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
- printf("\n\n************************\n%s", pszMessage);
- if (wxTheApp)
- wxMessageBox(pszMessage, "Error", wxOK | wxICON_ERROR);
- throw;
- //DebugBreak();
-}
-
-
void ParseString(const string& str, char c, vector<string>& v)
{
unsigned int i1 = 0;
@@ -268,6 +250,92 @@ bool ParseMoney(const char* pszIn, int64& nRet)
}
+vector<unsigned char> ParseHex(const char* psz)
+{
+ vector<unsigned char> vch;
+ while (isspace(*psz))
+ psz++;
+ vch.reserve((strlen(psz)+1)/3);
+
+ static char phexdigit[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,-1,-1,-1,-1,-1,
+ 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
+ -1,0xa,0xb,0xc,0xd,0xe,0xf,-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,0xa,0xb,0xc,0xd,0xe,0xf,-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,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
+
+ while (*psz)
+ {
+ char c = phexdigit[(unsigned char)*psz++];
+ if (c == -1)
+ break;
+ unsigned char n = (c << 4);
+ if (*psz)
+ {
+ char c = phexdigit[(unsigned char)*psz++];
+ if (c == -1)
+ break;
+ n |= c;
+ vch.push_back(n);
+ }
+ while (isspace(*psz))
+ psz++;
+ }
+
+ return vch;
+}
+
+vector<unsigned char> ParseHex(const std::string& str)
+{
+ return ParseHex(str.c_str());
+}
+
+
+
+
+
+
+void FormatException(char* pszMessage, std::exception* pex, const char* pszThread)
+{
+ char pszModule[MAX_PATH];
+ pszModule[0] = '\0';
+ GetModuleFileName(NULL, pszModule, sizeof(pszModule));
+ if (pex)
+ snprintf(pszMessage, 1000,
+ "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
+ else
+ snprintf(pszMessage, 1000,
+ "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
+}
+
+void LogException(std::exception* pex, const char* pszThread)
+{
+ char pszMessage[1000];
+ FormatException(pszMessage, pex, pszThread);
+ printf("\n%s", pszMessage);
+}
+
+void PrintException(std::exception* pex, const char* pszThread)
+{
+ char pszMessage[1000];
+ FormatException(pszMessage, pex, pszThread);
+ printf("\n\n************************\n%s\n", pszMessage);
+ if (wxTheApp)
+ wxMessageBox(pszMessage, "Error", wxOK | wxICON_ERROR);
+ throw;
+ //DebugBreak();
+}
@@ -363,7 +431,7 @@ void AddTimeData(unsigned int ip, int64 nTime)
if (vTimeOffsets.empty())
vTimeOffsets.push_back(0);
vTimeOffsets.push_back(nOffsetSample);
- printf("Added time data, samples %d, ip %08x, offset %+I64d (%+I64d minutes)\n", vTimeOffsets.size(), ip, vTimeOffsets.back(), vTimeOffsets.back()/60);
+ printf("Added time data, samples %d, offset %+I64d (%+I64d minutes)\n", vTimeOffsets.size(), vTimeOffsets.back(), vTimeOffsets.back()/60);
if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
{
sort(vTimeOffsets.begin(), vTimeOffsets.end());
diff --git a/util.h b/util.h
index 97617ab490..61f774a8d9 100644
--- a/util.h
+++ b/util.h
@@ -67,15 +67,22 @@ inline T& REF(const T& val)
extern bool fDebug;
+extern bool fPrintToDebugger;
+extern bool fPrintToConsole;
+extern map<string, string> mapArgs;
-void RandAddSeed(bool fPerfmon=false);
+void RandAddSeed();
+void RandAddSeedPerfmon();
int my_snprintf(char* buffer, size_t limit, const char* format, ...);
string strprintf(const char* format, ...);
bool error(const char* format, ...);
void PrintException(std::exception* pex, const char* pszThread);
+void LogException(std::exception* pex, const char* pszThread);
void ParseString(const string& str, char c, vector<string>& v);
string FormatMoney(int64 n, bool fPlus=false);
bool ParseMoney(const char* pszIn, int64& nRet);
+vector<unsigned char> ParseHex(const char* psz);
+vector<unsigned char> ParseHex(const std::string& str);
bool FileExists(const char* psz);
int GetFilesize(FILE* file);
uint64 GetRand(uint64 nMax);
@@ -94,6 +101,7 @@ void AddTimeData(unsigned int ip, int64 nTime);
+
// Wrapper to automatically initialize critical section
// Could use wxCriticalSection for portability, but it doesn't support TryEnterCriticalSection
class CCriticalSection
@@ -156,6 +164,85 @@ public:
+inline int OutputDebugStringF(const char* pszFormat, ...)
+{
+ int ret = 0;
+#ifdef __WXDEBUG__
+ if (!fPrintToConsole)
+ {
+ // print to debug.log
+ FILE* fileout = fopen("debug.log", "a");
+ if (fileout)
+ {
+ va_list arg_ptr;
+ va_start(arg_ptr, pszFormat);
+ ret = vfprintf(fileout, pszFormat, arg_ptr);
+ va_end(arg_ptr);
+ fclose(fileout);
+ }
+ }
+
+ if (fPrintToDebugger)
+ {
+ // accumulate a line at a time
+ static CCriticalSection cs_OutputDebugStringF;
+ CRITICAL_BLOCK(cs_OutputDebugStringF)
+ {
+ static char pszBuffer[50000];
+ static char* pend;
+ if (pend == NULL)
+ pend = pszBuffer;
+ va_list arg_ptr;
+ va_start(arg_ptr, pszFormat);
+ int limit = END(pszBuffer) - pend - 2;
+ int ret = _vsnprintf(pend, limit, pszFormat, arg_ptr);
+ va_end(arg_ptr);
+ if (ret < 0 || ret >= limit)
+ {
+ pend = END(pszBuffer) - 2;
+ *pend++ = '\n';
+ }
+ else
+ pend += ret;
+ *pend = '\0';
+ char* p1 = pszBuffer;
+ char* p2;
+ while (p2 = strchr(p1, '\n'))
+ {
+ p2++;
+ char c = *p2;
+ *p2 = '\0';
+ OutputDebugString(p1);
+ *p2 = c;
+ p1 = p2;
+ }
+ if (p1 != pszBuffer)
+ memmove(pszBuffer, p1, pend - p1 + 1);
+ pend -= (p1 - pszBuffer);
+ }
+ }
+#endif
+
+ if (fPrintToConsole)
+ {
+ // print to console
+ va_list arg_ptr;
+ va_start(arg_ptr, pszFormat);
+ ret = vprintf(pszFormat, arg_ptr);
+ va_end(arg_ptr);
+ }
+ return ret;
+}
+
+
+
+
+
+
+
+
+
+
inline string i64tostr(int64 n)
{
return strprintf("%"PRId64, n);
@@ -205,6 +292,11 @@ string HexStr(const T itbegin, const T itend, bool fSpaces=true)
return str;
}
+inline string HexStr(vector<unsigned char> vch, bool fSpaces=true)
+{
+ return HexStr(vch.begin(), vch.end(), fSpaces);
+}
+
template<typename T>
string HexNumStr(const T itbegin, const T itend, bool f0x=true)
{
@@ -222,75 +314,9 @@ void PrintHex(const T pbegin, const T pend, const char* pszFormat="%s", bool fSp
printf(pszFormat, HexStr(pbegin, pend, fSpaces).c_str());
}
-
-
-
-
-
-
-
-inline int OutputDebugStringF(const char* pszFormat, ...)
+inline void PrintHex(vector<unsigned char> vch, const char* pszFormat="%s", bool fSpaces=true)
{
-#ifdef __WXDEBUG__
- // log file
- FILE* fileout = fopen("debug.log", "a");
- if (fileout)
- {
- va_list arg_ptr;
- va_start(arg_ptr, pszFormat);
- vfprintf(fileout, pszFormat, arg_ptr);
- va_end(arg_ptr);
- fclose(fileout);
- }
-
- // accumulate a line at a time
- static CCriticalSection cs_OutputDebugStringF;
- CRITICAL_BLOCK(cs_OutputDebugStringF)
- {
- static char pszBuffer[50000];
- static char* pend;
- if (pend == NULL)
- pend = pszBuffer;
- va_list arg_ptr;
- va_start(arg_ptr, pszFormat);
- int limit = END(pszBuffer) - pend - 2;
- int ret = _vsnprintf(pend, limit, pszFormat, arg_ptr);
- va_end(arg_ptr);
- if (ret < 0 || ret >= limit)
- {
- pend = END(pszBuffer) - 2;
- *pend++ = '\n';
- }
- else
- pend += ret;
- *pend = '\0';
- char* p1 = pszBuffer;
- char* p2;
- while (p2 = strchr(p1, '\n'))
- {
- p2++;
- char c = *p2;
- *p2 = '\0';
- OutputDebugString(p1);
- *p2 = c;
- p1 = p2;
- }
- if (p1 != pszBuffer)
- memmove(pszBuffer, p1, pend - p1 + 1);
- pend -= (p1 - pszBuffer);
- return ret;
- }
-#endif
-
- if (!wxTheApp)
- {
- // print to console
- va_list arg_ptr;
- va_start(arg_ptr, pszFormat);
- vprintf(pszFormat, arg_ptr);
- va_end(arg_ptr);
- }
- return 0;
+ printf(pszFormat, HexStr(vch, fSpaces).c_str());
}