addr relaying fixes, proxy option and privacy patches, detect connect to self, non-final tx locktime changes, fix hide unconfirmed generated

This commit is contained in:
s_nakamoto 2009-10-29 02:52:48 +00:00
parent 6ccefea62a
commit cc0b4c3b62
19 changed files with 1216 additions and 346 deletions

View file

@ -1,4 +1,4 @@
BitCoin v0.1.6 ALPHA BitCoin v0.1.6 BETA
Copyright (c) 2009 Satoshi Nakamoto Copyright (c) 2009 Satoshi Nakamoto
Distributed under the MIT/X11 software license, see the accompanying Distributed under the MIT/X11 software license, see the accompanying
@ -19,10 +19,10 @@ Dependencies
Libraries you need to obtain separately to build: Libraries you need to obtain separately to build:
default path download default path download
wxWidgets \wxWidgets http://www.wxwidgets.org/downloads/ wxWidgets \wxwidgets http://www.wxwidgets.org/downloads/
OpenSSL \OpenSSL http://www.openssl.org/source/ OpenSSL \openssl http://www.openssl.org/source/
Berkeley DB \DB http://www.oracle.com/technology/software/products/berkeley-db/index.html Berkeley DB \db http://www.oracle.com/technology/software/products/berkeley-db/index.html
Boost \Boost http://www.boost.org/users/download/ Boost \boost http://www.boost.org/users/download/
Their licenses: Their licenses:
wxWidgets LGPL 2.1 with very liberal exceptions 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 Berkeley DB
----------- -----------
Using MinGW and MSYS: Using MinGW and MSYS:
cd \DB\build_unix cd \db\build_unix
sh ../dist/configure --enable-mingw --enable-cxx sh ../dist/configure --enable-mingw --enable-cxx
make make

19
db.cpp
View file

@ -121,10 +121,12 @@ void CDB::Close()
pdb->close(0); pdb->close(0);
delete pdb; delete pdb;
pdb = NULL; pdb = NULL;
dbenv.txn_checkpoint(0, 0, 0);
CRITICAL_BLOCK(cs_db) CRITICAL_BLOCK(cs_db)
{
dbenv.txn_checkpoint(0, 0, 0);
--mapFileUseCount[strFile]; --mapFileUseCount[strFile];
}
RandAddSeed(); RandAddSeed();
} }
@ -376,11 +378,11 @@ bool CTxDB::LoadBlockIndex()
{ {
if (pindexGenesisBlock == NULL) if (pindexGenesisBlock == NULL)
return true; return true;
return error("CTxDB::LoadBlockIndex() : hashBestChain not found\n"); return error("CTxDB::LoadBlockIndex() : hashBestChain not found");
} }
if (!mapBlockIndex.count(hashBestChain)) 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]; pindexBest = mapBlockIndex[hashBestChain];
nBestHeight = pindexBest->nHeight; nBestHeight = pindexBest->nHeight;
printf("LoadBlockIndex(): hashBestChain=%s height=%d\n", hashBestChain.ToString().substr(0,14).c_str(), nBestHeight); 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() CWalletDB::~CWalletDB()
{ {
// Flush whenever all handles to wallet.dat are closed // Flush whenever all handles to wallet.dat are closed
Close();
CRITICAL_BLOCK(cs_db) CRITICAL_BLOCK(cs_db)
{ {
Close(); // close includes a txn_checkpoint
map<string, int>::iterator mi = mapFileUseCount.find(strFile); map<string, int>::iterator mi = mapFileUseCount.find(strFile);
if (mi != mapFileUseCount.end()) if (mi != mapFileUseCount.end())
{ {
int nRefCount = (*mi).second; int nRefCount = (*mi).second;
if (nRefCount == 0) if (nRefCount == 0)
{ {
dbenv.txn_checkpoint(0, 0, 0);
dbenv.lsn_reset(strFile.c_str(), 0); dbenv.lsn_reset(strFile.c_str(), 0);
mapFileUseCount.erase(mi++); mapFileUseCount.erase(mi++);
} }
@ -600,6 +601,9 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
if (strKey == "nLimitProcessors") ssValue >> nLimitProcessors; if (strKey == "nLimitProcessors") ssValue >> nLimitProcessors;
if (strKey == "fMinimizeToTray") ssValue >> fMinimizeToTray; if (strKey == "fMinimizeToTray") ssValue >> fMinimizeToTray;
if (strKey == "fMinimizeOnClose") ssValue >> fMinimizeOnClose; 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("addrIncoming = %s\n", addrIncoming.ToString().c_str());
printf("fMinimizeToTray = %d\n", fMinimizeToTray); printf("fMinimizeToTray = %d\n", fMinimizeToTray);
printf("fMinimizeOnClose = %d\n", fMinimizeOnClose); 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. // 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. // 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 else
{ {
// Create new keyUser and set as default key // Create new keyUser and set as default key
RandAddSeed(true); RandAddSeedPerfmon();
keyUser.MakeNewKey(); keyUser.MakeNewKey();
if (!AddKey(keyUser)) if (!AddKey(keyUser))
return false; return false;

View file

@ -5,6 +5,7 @@
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable:4786) #pragma warning(disable:4786)
#pragma warning(disable:4804) #pragma warning(disable:4804)
#pragma warning(disable:4805)
#pragma warning(disable:4717) #pragma warning(disable:4717)
#endif #endif
#ifdef _WIN32_WINNT #ifdef _WIN32_WINNT
@ -62,6 +63,7 @@ using namespace boost;
#include "strlcpy.h"
#include "serialize.h" #include "serialize.h"
#include "uint256.h" #include "uint256.h"
#include "util.h" #include "util.h"

10
irc.cpp
View file

@ -163,6 +163,9 @@ void ThreadIRCSeed(void* parg)
int nErrorWait = 10; int nErrorWait = 10;
int nRetryWait = 10; int nRetryWait = 10;
if (fUseProxy && addrProxy.port == htons(9050))
return;
while (!fShutdown) while (!fShutdown)
{ {
CAddress addrConnect("216.155.130.130:6667"); CAddress addrConnect("216.155.130.130:6667");
@ -191,9 +194,10 @@ void ThreadIRCSeed(void* parg)
return; return;
} }
string strMyName = EncodeAddress(addrLocalHost); string strMyName;
if (addrLocalHost.IsRoutable() && !fUseProxy)
if (!addrLocalHost.IsRoutable()) strMyName = EncodeAddress(addrLocalHost);
else
strMyName = strprintf("x%u", GetRand(1000000000)); strMyName = strprintf("x%u", GetRand(1000000000));

2
key.h
View file

@ -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; typedef vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;

View file

@ -415,6 +415,10 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis
if (!CheckTransaction()) if (!CheckTransaction())
return error("AcceptTransaction() : CheckTransaction failed"); 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? // Do we already have it?
uint256 hash = GetHash(); uint256 hash = GetHash();
CRITICAL_BLOCK(cs_mapTransactions) CRITICAL_BLOCK(cs_mapTransactions)
@ -1214,6 +1218,12 @@ bool CBlock::AcceptBlock()
if (nTime <= pindexPrev->GetMedianTimePast()) if (nTime <= pindexPrev->GetMedianTimePast())
return error("AcceptBlock() : block's timestamp is too early"); 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 // Check proof of work
if (nBits != GetNextWorkRequired(pindexPrev)) if (nBits != GetNextWorkRequired(pindexPrev))
return error("AcceptBlock() : incorrect proof of work"); return error("AcceptBlock() : incorrect proof of work");
@ -1649,7 +1659,7 @@ bool ProcessMessages(CNode* pfrom)
CDataStream& vRecv = pfrom->vRecv; CDataStream& vRecv = pfrom->vRecv;
if (vRecv.empty()) if (vRecv.empty())
return true; return true;
printf("ProcessMessages(%d bytes)\n", vRecv.size()); //printf("ProcessMessages(%d bytes)\n", vRecv.size());
// //
// Message format // Message format
@ -1692,7 +1702,7 @@ bool ProcessMessages(CNode* pfrom)
{ {
// Rewind and wait for rest of message // Rewind and wait for rest of message
///// need a mechanism to give up waiting for overlong message size error ///// 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)); vRecv.insert(vRecv.begin(), BEGIN(hdr), END(hdr));
Sleep(100); Sleep(100);
break; break;
@ -1711,7 +1721,20 @@ bool ProcessMessages(CNode* pfrom)
fRet = ProcessMessage(pfrom, strCommand, vMsg); fRet = ProcessMessage(pfrom, strCommand, vMsg);
CheckForShutdown(2); 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) if (!fRet)
printf("ProcessMessage(%s, %d bytes) FAILED\n", strCommand.c_str(), nMessageSize); 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) bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{ {
static map<unsigned int, vector<unsigned char> > mapReuseKey; 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) if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0)
{ {
printf("dropmessages DROPPING RECV MESSAGE\n"); printf("dropmessages DROPPING RECV MESSAGE\n");
@ -1735,18 +1759,32 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (strCommand == "version") if (strCommand == "version")
{ {
// Can only do this once // Each connection can only send one version message
if (pfrom->nVersion != 0) if (pfrom->nVersion != 0)
return false; return false;
int64 nTime; int64 nTime;
CAddress addrMe; CAddress addrMe;
CAddress addrFrom;
uint64 nNonce = 1;
vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe; vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;
if (pfrom->nVersion >= 106 && !vRecv.empty())
vRecv >> addrFrom >> nNonce;
if (pfrom->nVersion == 0) if (pfrom->nVersion == 0)
return false; 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->vSend.SetVersion(min(pfrom->nVersion, VERSION));
pfrom->vRecv.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->PushMessage("getblocks", CBlockLocator(pindexBest), uint256(0));
} }
pfrom->fSuccessfullyConnected = true;
printf("version message: version %d\n", pfrom->nVersion); printf("version message: version %d\n", pfrom->nVersion);
} }
@ -1800,16 +1840,16 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (fShutdown) if (fShutdown)
return true; return true;
AddAddress(addrdb, addr); 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 // Put on lists to send to other nodes
pfrom->setAddrKnown.insert(addr);
CRITICAL_BLOCK(cs_vNodes) CRITICAL_BLOCK(cs_vNodes)
foreach(CNode* pnode, vNodes) foreach(CNode* pnode, vNodes)
if (!pnode->setAddrKnown.count(addr)) pnode->PushAddress(addr);
pnode->vAddrToSend.push_back(addr);
} }
} }
pfrom->fGetAddr = false;
} }
@ -2009,7 +2049,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
return true; return true;
const CAddress& addr = item.second; const CAddress& addr = item.second;
if (addr.nTime > nSince) if (addr.nTime > nSince)
pfrom->vAddrToSend.push_back(addr); pfrom->PushAddress(addr);
} }
} }
} }
@ -2108,8 +2148,11 @@ bool SendMessages(CNode* pto)
vector<CAddress> vAddrToSend; vector<CAddress> vAddrToSend;
vAddrToSend.reserve(pto->vAddrToSend.size()); vAddrToSend.reserve(pto->vAddrToSend.size());
foreach(const CAddress& addr, pto->vAddrToSend) 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); vAddrToSend.push_back(addr);
}
pto->vAddrToSend.clear(); pto->vAddrToSend.clear();
if (!vAddrToSend.empty()) if (!vAddrToSend.empty())
pto->PushMessage("addr", vAddrToSend); pto->PushMessage("addr", vAddrToSend);
@ -2193,7 +2236,7 @@ void GenerateBitcoins(bool fGenerate)
if (fLimitProcessors && nProcessors > nLimitProcessors) if (fLimitProcessors && nProcessors > nLimitProcessors)
nProcessors = nLimitProcessors; nProcessors = nLimitProcessors;
int nAddThreads = nProcessors - vnThreadsRunning[3]; 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++) for (int i = 0; i < nAddThreads; i++)
if (_beginthread(ThreadBitcoinMiner, 0, NULL) == -1) if (_beginthread(ThreadBitcoinMiner, 0, NULL) == -1)
printf("Error: _beginthread(ThreadBitcoinMiner) failed\n"); printf("Error: _beginthread(ThreadBitcoinMiner) failed\n");
@ -2207,7 +2250,7 @@ void ThreadBitcoinMiner(void* parg)
try try
{ {
bool fRet = BitcoinMiner(); bool fRet = BitcoinMiner();
printf("BitcoinMiner returned %s\n\n\n", fRet ? "true" : "false"); printf("BitcoinMiner returned %s\n", fRet ? "true" : "false");
vnThreadsRunning[3]--; vnThreadsRunning[3]--;
} }
catch (std::exception& e) { catch (std::exception& e) {
@ -2737,7 +2780,7 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
else else
strError = "Error: Transaction creation failed "; strError = "Error: Transaction creation failed ";
wxMessageBox(strError, "Sending..."); wxMessageBox(strError, "Sending...");
return error("SendMoney() : %s\n", strError.c_str()); return error("SendMoney() : %s", strError.c_str());
} }
if (!CommitTransactionSpent(wtxNew, key)) if (!CommitTransactionSpent(wtxNew, key))
{ {

16
main.h
View file

@ -366,7 +366,7 @@ public:
int nVersion; int nVersion;
vector<CTxIn> vin; vector<CTxIn> vin;
vector<CTxOut> vout; vector<CTxOut> vout;
int nLockTime; unsigned int nLockTime;
CTransaction() CTransaction()
@ -401,9 +401,15 @@ public:
return SerializeHash(*this); 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; return true;
foreach(const CTxIn& txin, vin) foreach(const CTxIn& txin, vin)
if (!txin.IsFinal()) if (!txin.IsFinal())
@ -686,8 +692,9 @@ public:
char fSpent; char fSpent;
//// probably need to sign the order info so know it came from payer //// probably need to sign the order info so know it came from payer
// memory only // memory only UI hints
mutable unsigned int nTimeDisplayed; mutable unsigned int nTimeDisplayed;
mutable int nLinesDisplayed;
CWalletTx() CWalletTx()
@ -712,6 +719,7 @@ public:
fFromMe = false; fFromMe = false;
fSpent = false; fSpent = false;
nTimeDisplayed = 0; nTimeDisplayed = 0;
nLinesDisplayed = 0;
} }
IMPLEMENT_SERIALIZE IMPLEMENT_SERIALIZE

View file

@ -17,8 +17,8 @@ endif
INCLUDEPATHS=-I"/boost" -I"/DB/build_unix" -I"/OpenSSL/include" -I"/wxWidgets/lib/vc_lib/mswd" -I"/wxWidgets/include" 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" LIBPATHS=-L"/db/build_unix" -L"/openssl/out" -L"/wxwidgets/lib/gcc_lib"
LIBS= \ LIBS= \
-l db_cxx \ -l db_cxx \
-l eay32 \ -l eay32 \

181
net.cpp
View file

@ -8,6 +8,7 @@
void ThreadMessageHandler2(void* parg); void ThreadMessageHandler2(void* parg);
void ThreadSocketHandler2(void* parg); void ThreadSocketHandler2(void* parg);
void ThreadOpenConnections2(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); CAddress addrLocalHost(0, DEFAULT_PORT, nLocalServices);
CNode nodeLocalHost(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices)); CNode nodeLocalHost(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
CNode* pnodeLocalHost = &nodeLocalHost; CNode* pnodeLocalHost = &nodeLocalHost;
uint64 nLocalHostNonce = 0;
bool fShutdown = false; bool fShutdown = false;
array<int, 10> vnThreadsRunning; array<int, 10> vnThreadsRunning;
SOCKET hListenSocket = INVALID_SOCKET;
vector<CNode*> vNodes; vector<CNode*> vNodes;
CCriticalSection cs_vNodes; CCriticalSection cs_vNodes;
@ -34,9 +37,11 @@ deque<pair<int64, CInv> > vRelayExpiration;
CCriticalSection cs_mapRelay; CCriticalSection cs_mapRelay;
map<CInv, int64> mapAlreadyAskedFor; map<CInv, int64> mapAlreadyAskedFor;
// Settings
int fUseProxy = false;
CAddress addrProxy("127.0.0.1:9050");
CAddress addrProxy;
bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet) bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
{ {
@ -47,7 +52,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
return false; return false;
bool fRoutable = !(addrConnect.GetByte(3) == 10 || (addrConnect.GetByte(3) == 192 && addrConnect.GetByte(2) == 168)); 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()); struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR) if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
@ -69,18 +74,18 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
if (ret != nSize) if (ret != nSize)
{ {
closesocket(hSocket); closesocket(hSocket);
return error("Error sending to proxy\n"); return error("Error sending to proxy");
} }
char pchRet[8]; char pchRet[8];
if (recv(hSocket, pchRet, 8, 0) != 8) if (recv(hSocket, pchRet, 8, 0) != 8)
{ {
closesocket(hSocket); closesocket(hSocket);
return error("Error reading proxy response\n"); return error("Error reading proxy response");
} }
if (pchRet[1] != 0x5a) if (pchRet[1] != 0x5a)
{ {
closesocket(hSocket); 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()); 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; SOCKET hSocket;
if (!ConnectSocket(addrConnect, 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); send(hSocket, pszGet, strlen(pszGet), 0);
@ -131,7 +136,7 @@ bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const cha
} }
} }
closesocket(hSocket); 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* pszGet;
char* pszKeyword; char* pszKeyword;
if (fUseProxy)
return false;
for (int nLookup = 0; nLookup <= 1; nLookup++) for (int nLookup = 0; nLookup <= 1; nLookup++)
for (int nHost = 1; nHost <= 2; nHost++) 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()); printf("disconnecting node %s\n", addr.ToStringLog().c_str());
closesocket(hSocket); closesocket(hSocket);
// If outbound and never got version message, mark address as failed // If outbound and never got version message, mark address as failed
if (!fInbound && nVersion == 0) if (!fInbound && !fSuccessfullyConnected)
CRITICAL_BLOCK(cs_mapAddresses) CRITICAL_BLOCK(cs_mapAddresses)
mapAddresses[addr.GetKey()].nLastFailed = GetTime(); mapAddresses[addr.GetKey()].nLastFailed = GetTime();
@ -458,18 +466,18 @@ void ThreadSocketHandler(void* parg)
loop loop
{ {
vnThreadsRunning[0] = true; vnThreadsRunning[0]++;
CheckForShutdown(0); CheckForShutdown(0);
try try
{ {
ThreadSocketHandler2(parg); ThreadSocketHandler2(parg);
vnThreadsRunning[0] = false; vnThreadsRunning[0]--;
} }
catch (std::exception& e) { catch (std::exception& e) {
vnThreadsRunning[0] = false; vnThreadsRunning[0]--;
PrintException(&e, "ThreadSocketHandler()"); PrintException(&e, "ThreadSocketHandler()");
} catch (...) { } catch (...) {
vnThreadsRunning[0] = false; vnThreadsRunning[0]--;
PrintException(NULL, "ThreadSocketHandler()"); PrintException(NULL, "ThreadSocketHandler()");
} }
Sleep(5000); Sleep(5000);
@ -479,7 +487,6 @@ void ThreadSocketHandler(void* parg)
void ThreadSocketHandler2(void* parg) void ThreadSocketHandler2(void* parg)
{ {
printf("ThreadSocketHandler started\n"); printf("ThreadSocketHandler started\n");
SOCKET hListenSocket = *(SOCKET*)parg;
list<CNode*> vNodesDisconnected; list<CNode*> vNodesDisconnected;
int nPrevNodeCount = 0; int nPrevNodeCount = 0;
@ -498,7 +505,7 @@ void ThreadSocketHandler2(void* parg)
{ {
// remove from vNodes // remove from vNodes
vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end()); vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
pnode->Disconnect(); pnode->DoDisconnect();
// hold in disconnected pool until all refs are released // hold in disconnected pool until all refs are released
pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 5 * 60); 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); int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, NULL, &timeout);
vnThreadsRunning[0] = true; vnThreadsRunning[0]++;
CheckForShutdown(0); CheckForShutdown(0);
if (nSelect == SOCKET_ERROR) if (nSelect == SOCKET_ERROR)
{ {
@ -577,7 +584,6 @@ void ThreadSocketHandler2(void* parg)
} }
Sleep(timeout.tv_usec/1000); Sleep(timeout.tv_usec/1000);
} }
RandAddSeed();
//// debug print //// debug print
//foreach(CNode* pnode, vNodes) //foreach(CNode* pnode, vNodes)
@ -711,18 +717,18 @@ void ThreadOpenConnections(void* parg)
loop loop
{ {
vnThreadsRunning[1] = true; vnThreadsRunning[1]++;
CheckForShutdown(1); CheckForShutdown(1);
try try
{ {
ThreadOpenConnections2(parg); ThreadOpenConnections2(parg);
vnThreadsRunning[1] = false; vnThreadsRunning[1]--;
} }
catch (std::exception& e) { catch (std::exception& e) {
vnThreadsRunning[1] = false; vnThreadsRunning[1]--;
PrintException(&e, "ThreadOpenConnections()"); PrintException(&e, "ThreadOpenConnections()");
} catch (...) { } catch (...) {
vnThreadsRunning[1] = false; vnThreadsRunning[1]--;
PrintException(NULL, "ThreadOpenConnections()"); PrintException(NULL, "ThreadOpenConnections()");
} }
Sleep(5000); Sleep(5000);
@ -733,6 +739,13 @@ void ThreadOpenConnections2(void* parg)
{ {
printf("ThreadOpenConnections started\n"); printf("ThreadOpenConnections started\n");
// Connect to one specified address
while (mapArgs.count("/connect"))
{
OpenNetworkConnection(CAddress(mapArgs["/connect"].c_str()));
Sleep(10000);
}
// Initiate network connections // Initiate network connections
int nTry = 0; int nTry = 0;
bool fIRCOnly = false; bool fIRCOnly = false;
@ -740,14 +753,14 @@ void ThreadOpenConnections2(void* parg)
loop loop
{ {
// Wait // Wait
vnThreadsRunning[1] = false; vnThreadsRunning[1]--;
Sleep(500); Sleep(500);
while (vNodes.size() >= nMaxConnections || vNodes.size() >= mapAddresses.size()) while (vNodes.size() >= nMaxConnections || vNodes.size() >= mapAddresses.size())
{ {
CheckForShutdown(1); CheckForShutdown(1);
Sleep(2000); Sleep(2000);
} }
vnThreadsRunning[1] = true; vnThreadsRunning[1]++;
CheckForShutdown(1); CheckForShutdown(1);
@ -835,45 +848,50 @@ void ThreadOpenConnections2(void* parg)
// Once we've chosen an IP, we'll try every given port before moving on // Once we've chosen an IP, we'll try every given port before moving on
foreach(const CAddress& addrConnect, (*mi).second) foreach(const CAddress& addrConnect, (*mi).second)
{ if (OpenNetworkConnection(addrConnect))
// break;
// Initiate outbound network connection
//
CheckForShutdown(1);
if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
continue;
vnThreadsRunning[1] = false;
CNode* pnode = ConnectNode(addrConnect);
vnThreadsRunning[1] = true;
CheckForShutdown(1);
if (!pnode)
continue;
pnode->fNetworkNode = true;
if (addrLocalHost.IsRoutable())
{
// Advertise our address
vector<CAddress> vAddrToSend;
vAddrToSend.push_back(addrLocalHost);
pnode->PushMessage("addr", vAddrToSend);
}
// Get as many addresses as we can
pnode->PushMessage("getaddr");
////// 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);
break;
}
} }
} }
bool OpenNetworkConnection(const CAddress& addrConnect)
{
//
// Initiate outbound network connection
//
CheckForShutdown(1);
if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
return false;
vnThreadsRunning[1]--;
CNode* pnode = ConnectNode(addrConnect);
vnThreadsRunning[1]++;
CheckForShutdown(1);
if (!pnode)
return false;
pnode->fNetworkNode = true;
if (addrLocalHost.IsRoutable() && !fUseProxy)
{
// Advertise our address
vector<CAddress> vAddrToSend;
vAddrToSend.push_back(addrLocalHost);
pnode->PushMessage("addr", vAddrToSend);
}
// Get as many addresses as we can
pnode->PushMessage("getaddr");
pnode->fGetAddr = true; // don't relay the results of the getaddr
////// 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 loop
{ {
vnThreadsRunning[2] = true; vnThreadsRunning[2]++;
CheckForShutdown(2); CheckForShutdown(2);
try try
{ {
ThreadMessageHandler2(parg); ThreadMessageHandler2(parg);
vnThreadsRunning[2] = false; vnThreadsRunning[2]--;
} }
catch (std::exception& e) { catch (std::exception& e) {
vnThreadsRunning[2] = false; vnThreadsRunning[2]--;
PrintException(&e, "ThreadMessageHandler()"); PrintException(&e, "ThreadMessageHandler()");
} catch (...) { } catch (...) {
vnThreadsRunning[2] = false; vnThreadsRunning[2]--;
PrintException(NULL, "ThreadMessageHandler()"); PrintException(NULL, "ThreadMessageHandler()");
} }
Sleep(5000); Sleep(5000);
@ -931,9 +949,9 @@ void ThreadMessageHandler2(void* parg)
} }
// Wait and allow messages to bunch up // Wait and allow messages to bunch up
vnThreadsRunning[2] = false; vnThreadsRunning[2]--;
Sleep(100); Sleep(100);
vnThreadsRunning[2] = true; vnThreadsRunning[2]++;
CheckForShutdown(2); CheckForShutdown(2);
} }
} }
@ -982,7 +1000,7 @@ bool StartNode(string& strError)
printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str()); printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
// Create socket for listening for incoming connections // 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) if (hListenSocket == INVALID_SOCKET)
{ {
strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError()); 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 // Get our external IP address for incoming connections
if (addrIncoming.ip) if (fUseProxy)
addrLocalHost.ip = addrIncoming.ip;
if (GetMyExternalIP(addrLocalHost.ip))
{ {
addrIncoming = addrLocalHost; // Proxies can't take incoming connections
CWalletDB().WriteSetting("addrIncoming", addrIncoming); 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 // Get addresses from IRC and advertise ours
@ -1040,7 +1066,7 @@ bool StartNode(string& strError)
// //
// Start threads // Start threads
// //
if (_beginthread(ThreadSocketHandler, 0, new SOCKET(hListenSocket)) == -1) if (_beginthread(ThreadSocketHandler, 0, NULL) == -1)
{ {
strError = "Error: _beginthread(ThreadSocketHandler) failed"; strError = "Error: _beginthread(ThreadSocketHandler) failed";
printf("%s\n", strError.c_str()); printf("%s\n", strError.c_str());
@ -1094,10 +1120,15 @@ void CheckForShutdown(int n)
if (fShutdown) if (fShutdown)
{ {
if (n != -1) if (n != -1)
vnThreadsRunning[n] = false; if (--vnThreadsRunning[n] < 0)
vnThreadsRunning[n] = 0;
if (n == 0) if (n == 0)
{
foreach(CNode* pnode, vNodes) foreach(CNode* pnode, vNodes)
closesocket(pnode->hSocket); closesocket(pnode->hSocket);
closesocket(hListenSocket);
}
printf("Thread %d exiting\n", n);
_endthread(); _endthread();
} }
} }

131
net.h
View file

@ -174,7 +174,7 @@ public:
{ {
nServices = nServicesIn; nServices = nServicesIn;
memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
ip = 0; ip = INADDR_NONE;
port = DEFAULT_PORT; port = DEFAULT_PORT;
nTime = GetAdjustedTime(); nTime = GetAdjustedTime();
nLastFailed = 0; nLastFailed = 0;
@ -183,7 +183,7 @@ public:
if (strlen(pszIn) > ARRAYLEN(psz)-1) if (strlen(pszIn) > ARRAYLEN(psz)-1)
return; return;
strcpy(psz, pszIn); 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) if (sscanf(psz, "%u.%u.%u.%u:%u", &a, &b, &c, &d, &e) < 4)
return; return;
char* pszPort = strchr(psz, ':'); char* pszPort = strchr(psz, ':');
@ -191,6 +191,10 @@ public:
{ {
*pszPort++ = '\0'; *pszPort++ = '\0';
port = htons(atoi(pszPort)); port = htons(atoi(pszPort));
if (atoi(pszPort) > USHRT_MAX)
port = htons(USHRT_MAX);
if (atoi(pszPort) < 0)
port = htons(0);
} }
ip = inet_addr(psz); ip = inet_addr(psz);
} }
@ -215,6 +219,11 @@ public:
a.port == b.port); 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) friend inline bool operator<(const CAddress& a, const CAddress& b)
{ {
int ret = memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved)); 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)); 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 string ToStringLog() const
{ {
return ""; return "";
@ -416,6 +430,7 @@ extern bool fClient;
extern uint64 nLocalServices; extern uint64 nLocalServices;
extern CAddress addrLocalHost; extern CAddress addrLocalHost;
extern CNode* pnodeLocalHost; extern CNode* pnodeLocalHost;
extern uint64 nLocalHostNonce;
extern bool fShutdown; extern bool fShutdown;
extern array<int, 10> vnThreadsRunning; extern array<int, 10> vnThreadsRunning;
extern vector<CNode*> vNodes; extern vector<CNode*> vNodes;
@ -426,6 +441,9 @@ extern map<CInv, CDataStream> mapRelay;
extern deque<pair<int64, CInv> > vRelayExpiration; extern deque<pair<int64, CInv> > vRelayExpiration;
extern CCriticalSection cs_mapRelay; extern CCriticalSection cs_mapRelay;
extern map<CInv, int64> mapAlreadyAskedFor; extern map<CInv, int64> mapAlreadyAskedFor;
// Settings
extern int fUseProxy;
extern CAddress addrProxy; extern CAddress addrProxy;
@ -448,6 +466,7 @@ public:
bool fClient; bool fClient;
bool fInbound; bool fInbound;
bool fNetworkNode; bool fNetworkNode;
bool fSuccessfullyConnected;
bool fDisconnect; bool fDisconnect;
protected: protected:
int nRefCount; int nRefCount;
@ -459,6 +478,7 @@ public:
// flood // flood
vector<CAddress> vAddrToSend; vector<CAddress> vAddrToSend;
set<CAddress> setAddrKnown; set<CAddress> setAddrKnown;
bool fGetAddr;
// inventory based relay // inventory based relay
set<CInv> setInventoryKnown; set<CInv> setInventoryKnown;
@ -483,15 +503,20 @@ public:
fClient = false; // set by version message fClient = false; // set by version message
fInbound = fInboundIn; fInbound = fInboundIn;
fNetworkNode = false; fNetworkNode = false;
fSuccessfullyConnected = false;
fDisconnect = false; fDisconnect = false;
nRefCount = 0; nRefCount = 0;
nReleaseTime = 0; nReleaseTime = 0;
fGetAddr = false;
vfSubscribe.assign(256, false); vfSubscribe.assign(256, false);
// Push a version message // Push a version message
/// when NTP implemented, change to just nTime = GetAdjustedTime() /// when NTP implemented, change to just nTime = GetAdjustedTime()
int64 nTime = (fInbound ? GetAdjustedTime() : GetTime()); 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() ~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) void AddInventoryKnown(const CInv& inv)
{ {
CRITICAL_BLOCK(cs_inventory) CRITICAL_BLOCK(cs_inventory)
@ -562,7 +602,6 @@ public:
} }
void BeginMessage(const char* pszCommand) void BeginMessage(const char* pszCommand)
{ {
EnterCriticalSection(&cs_vSend); EnterCriticalSection(&cs_vSend);
@ -570,7 +609,7 @@ public:
AbortMessage(); AbortMessage();
nPushPos = vSend.size(); nPushPos = vSend.size();
vSend << CMessageHeader(pszCommand, 0); vSend << CMessageHeader(pszCommand, 0);
printf("sending: %-12s ", pszCommand); printf("sending: %s ", pszCommand);
} }
void AbortMessage() 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 PushRequest(const char* pszCommand,
void (*fn)(void*, CDataStream&), void* param1) void (*fn)(void*, CDataStream&), void* param1)
@ -750,7 +869,7 @@ public:
bool IsSubscribed(unsigned int nChannel); bool IsSubscribed(unsigned int nChannel);
void Subscribe(unsigned int nChannel, unsigned int nHops=0); void Subscribe(unsigned int nChannel, unsigned int nHops=0);
void CancelSubscribe(unsigned int nChannel); void CancelSubscribe(unsigned int nChannel);
void Disconnect(); void DoDisconnect();
}; };

View file

@ -19,7 +19,7 @@ class CScript;
class CDataStream; class CDataStream;
class CAutoFile; class CAutoFile;
static const int VERSION = 105; static const int VERSION = 106;

84
strlcpy.h Normal file
View file

@ -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 */
}

223
ui.cpp
View file

@ -497,7 +497,7 @@ string SingleLine(const string& strIn)
return strOut; 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 nTime = wtx.nTimeDisplayed = wtx.GetTxTime();
int64 nCredit = wtx.GetCredit(); int64 nCredit = wtx.GetCredit();
@ -506,14 +506,11 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
uint256 hash = wtx.GetHash(); uint256 hash = wtx.GetHash();
string strStatus = FormatTxStatus(wtx); string strStatus = FormatTxStatus(wtx);
map<string, string> mapValue = wtx.mapValue; map<string, string> mapValue = wtx.mapValue;
wtx.nLinesDisplayed = 1;
// Filter // Filter
if (wtx.IsCoinBase()) if (wtx.IsCoinBase())
{ {
// View->Show Generated
if (!fShowGenerated)
return;
// Don't show generated coin until confirmed by at least one block after it // 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. // 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) if (wtx.GetDepthInMainChain() < 2)
{ {
// In case it was previously displayed wtx.nLinesDisplayed = 0;
DeleteLine(hash); return false;
return;
} }
// View->Show Generated
if (!fShowGenerated)
return false;
} }
// Find the block the tx is in // Find the block the tx is in
@ -644,6 +644,7 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
// Debit // Debit
// //
int64 nTxFee = nDebit - wtx.GetValueOut(); int64 nTxFee = nDebit - wtx.GetValueOut();
wtx.nLinesDisplayed = 0;
for (int nOut = 0; nOut < wtx.vout.size(); nOut++) for (int nOut = 0; nOut < wtx.vout.size(); nOut++)
{ {
const CTxOut& txout = wtx.vout[nOut]; const CTxOut& txout = wtx.vout[nOut];
@ -685,6 +686,7 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
SingleLine(strDescription), SingleLine(strDescription),
FormatMoney(-nValue, true), FormatMoney(-nValue, true),
""); "");
wtx.nLinesDisplayed++;
} }
} }
else else
@ -706,12 +708,14 @@ void CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
""); "");
} }
} }
return true;
} }
void CMainFrame::RefreshStatus() void CMainFrame::RefreshStatus()
{ {
static int nLastTop; static int nLastTop;
int nTop = m_listCtrl->GetTopItem(); int nTop = max((int)m_listCtrl->GetTopItem(), 0);
if (nTop == nLastTop && pindexBestLast == pindexBest) if (nTop == nLastTop && pindexBestLast == pindexBest)
return; return;
@ -729,7 +733,7 @@ void CMainFrame::RefreshStatus()
nLastTop = nTop; nLastTop = nTop;
pindexBestLast = pindexBest; 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)); uint256 hash((string)GetItemText(m_listCtrl, nIndex, 1));
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash); map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
@ -738,9 +742,12 @@ void CMainFrame::RefreshStatus()
printf("CMainFrame::RefreshStatus() : tx not found in mapWallet\n"); printf("CMainFrame::RefreshStatus() : tx not found in mapWallet\n");
continue; continue;
} }
const CWalletTx& wtx = (*mi).second; CWalletTx& wtx = (*mi).second;
if (wtx.IsCoinBase() || wtx.GetTxTime() != wtx.nTimeDisplayed) if (wtx.IsCoinBase() || wtx.GetTxTime() != wtx.nTimeDisplayed)
InsertTransaction(wtx, false, nIndex); {
if (!InsertTransaction(wtx, false, nIndex))
m_listCtrl->DeleteItem(nIndex--);
}
else else
m_listCtrl->SetItem(nIndex, 2, FormatTxStatus(wtx)); m_listCtrl->SetItem(nIndex, 2, FormatTxStatus(wtx));
} }
@ -801,6 +808,9 @@ void CMainFrame::OnIdle(wxIdleEvent& event)
} }
printf("RefreshListCtrl done\n"); printf("RefreshListCtrl done\n");
// Update transaction total display
MainFrameRepaint();
} }
else else
{ {
@ -834,31 +844,54 @@ void DelayedRepaint(void* parg)
return; return;
fOneThread = true; fOneThread = true;
Sleep(1000); Sleep(1000);
printf("DelayedRepaint()\n");
MainFrameRepaint(); MainFrameRepaint();
fOneThread = false; fOneThread = false;
} }
void CMainFrame::OnPaintListCtrl(wxPaintEvent& event) void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
{ {
if (ptaskbaricon)
ptaskbaricon->UpdateTooltip();
// Update listctrl contents // Update listctrl contents
if (!vWalletUpdated.empty()) if (!vWalletUpdated.empty())
{ {
TRY_CRITICAL_BLOCK(cs_mapWallet) TRY_CRITICAL_BLOCK(cs_mapWallet)
{ {
bool fInserted = false;
foreach(uint256 hash, vWalletUpdated) foreach(uint256 hash, vWalletUpdated)
{ {
map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash); map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
if (mi != mapWallet.end()) if (mi != mapWallet.end())
InsertTransaction((*mi).second, false); fInserted |= InsertTransaction((*mi).second, false);
} }
m_listCtrl->ScrollList(0, INT_MAX);
vWalletUpdated.clear(); vWalletUpdated.clear();
if (fInserted)
m_listCtrl->ScrollList(0, INT_MAX);
} }
} }
// Update status column of visible items only // Update status column of visible items only
RefreshStatus(); 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 // Update status bar
string strGen = ""; string strGen = "";
if (fGenerateBitcoins) if (fGenerateBitcoins)
@ -867,17 +900,9 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
strGen = "(not connected)"; strGen = "(not connected)";
m_statusBar->SetStatusText(strGen, 1); 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); 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 // mapWallet was locked, try again later
if (!vWalletUpdated.empty() || !fRefreshed) if (!vWalletUpdated.empty() || !fRefreshed)
_beginthread(DelayedRepaint, 0, NULL); _beginthread(DelayedRepaint, 0, NULL);
@ -1350,6 +1375,14 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent)
m_checkBoxMinimizeOnClose->Enable(fMinimizeToTray); m_checkBoxMinimizeOnClose->Enable(fMinimizeToTray);
m_checkBoxMinimizeOnClose->SetValue(fMinimizeToTray && fMinimizeOnClose); m_checkBoxMinimizeOnClose->SetValue(fMinimizeToTray && fMinimizeOnClose);
fTmpMinimizeOnClose = 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(); 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) void COptionsDialog::OnButtonOK(wxCommandEvent& event)
{ {
OnButtonApply(event); OnButtonApply(event);
@ -1446,6 +1507,18 @@ void COptionsDialog::OnButtonApply(wxCommandEvent& event)
fMinimizeOnClose = (fMinimizeToTray ? m_checkBoxMinimizeOnClose->GetValue() : fTmpMinimizeOnClose); fMinimizeOnClose = (fMinimizeToTray ? m_checkBoxMinimizeOnClose->GetValue() : fTmpMinimizeOnClose);
walletdb.WriteSetting("fMinimizeOnClose", fMinimizeOnClose); 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; nPrice = nPriceIn;
wtx = wtxIn; wtx = wtxIn;
start = wxDateTime::UNow(); start = wxDateTime::UNow();
strStatus = ""; memset(pszStatus, 0, sizeof(pszStatus));
fCanCancel = true; fCanCancel = true;
fAbort = false; fAbort = false;
fSuccess = false; fSuccess = false;
@ -1721,10 +1794,10 @@ void CSendingDialog::OnButtonCancel(wxCommandEvent& event)
void CSendingDialog::OnPaint(wxPaintEvent& event) void CSendingDialog::OnPaint(wxPaintEvent& event)
{ {
if (strStatus.size() > 130) if (strlen(pszStatus) > 130)
m_textCtrlStatus->SetValue(string("\n") + strStatus); m_textCtrlStatus->SetValue(string("\n") + pszStatus);
else else
m_textCtrlStatus->SetValue(string("\n\n") + strStatus); m_textCtrlStatus->SetValue(string("\n\n") + pszStatus);
m_staticTextSending->SetFocus(); m_staticTextSending->SetFocus();
if (!fCanCancel) if (!fCanCancel)
m_buttonCancel->Enable(false); m_buttonCancel->Enable(false);
@ -1736,7 +1809,7 @@ void CSendingDialog::OnPaint(wxPaintEvent& event)
} }
if (fAbort && fCanCancel && IsShown()) if (fAbort && fCanCancel && IsShown())
{ {
strStatus = "CANCELLED"; strcpy(pszStatus, "CANCELLED");
m_buttonOK->Enable(true); m_buttonOK->Enable(true);
m_buttonOK->SetFocus(); m_buttonOK->SetFocus();
m_buttonCancel->Enable(false); m_buttonCancel->Enable(false);
@ -1777,7 +1850,8 @@ bool CSendingDialog::Status()
} }
if (fAbort && fCanCancel) if (fAbort && fCanCancel)
{ {
strStatus = "CANCELLED"; memset(pszStatus, 0, 10);
strcpy(pszStatus, "CANCELLED");
Repaint(); Repaint();
fWorkDone = true; fWorkDone = true;
return false; return false;
@ -1789,7 +1863,12 @@ bool CSendingDialog::Status(const string& str)
{ {
if (!Status()) if (!Status())
return false; 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(); Repaint();
return true; return true;
} }
@ -1950,8 +2029,8 @@ void CSendingDialog::OnReply3(CDataStream& vRecv)
if (nRet > 0) if (nRet > 0)
{ {
Error("The payment was sent, but the recipient was unable to verify it.\n" 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" "The transaction is recorded and will credit to the recipient,\n"
"but without comment information."); "but the comment information will be blank.");
return; return;
} }
} }
@ -3092,6 +3171,7 @@ END_EVENT_TABLE()
void CMyTaskBarIcon::Show(bool fShow) void CMyTaskBarIcon::Show(bool fShow)
{ {
static char pszPrevTip[200];
if (fShow) if (fShow)
{ {
string strTooltip = "Bitcoin"; string strTooltip = "Bitcoin";
@ -3099,10 +3179,17 @@ void CMyTaskBarIcon::Show(bool fShow)
strTooltip = "Bitcoin - Generating"; strTooltip = "Bitcoin - Generating";
if (fGenerateBitcoins && vNodes.empty()) if (fGenerateBitcoins && vNodes.empty())
strTooltip = "Bitcoin - (not connected)"; 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 else
{ {
strlcpy(pszPrevTip, "", sizeof(pszPrevTip));
RemoveIcon(); RemoveIcon();
} }
} }
@ -3301,12 +3388,12 @@ bool CMyApp::OnInit2()
if (mapArgs.count("/datadir")) if (mapArgs.count("/datadir"))
strSetDataDir = mapArgs["/datadir"]; strSetDataDir = mapArgs["/datadir"];
if (mapArgs.count("/proxy"))
addrProxy = CAddress(mapArgs["/proxy"].c_str());
if (mapArgs.count("/debug")) if (mapArgs.count("/debug"))
fDebug = true; fDebug = true;
if (mapArgs.count("/printtodebugger"))
fPrintToDebugger = true;
if (mapArgs.count("/dropmessages")) if (mapArgs.count("/dropmessages"))
{ {
nDropMessagesTest = atoi(mapArgs["/dropmessages"]); nDropMessagesTest = atoi(mapArgs["/dropmessages"]);
@ -3380,6 +3467,20 @@ bool CMyApp::OnInit2()
return false; 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.count("/gen"))
{ {
if (mapArgs["/gen"].empty()) if (mapArgs["/gen"].empty())
@ -3404,7 +3505,7 @@ bool CMyApp::OnInit2()
return false; return false;
} }
//RandAddSeedPerfmon(); RandAddSeedPerfmon();
if (!StartNode(strErrors)) if (!StartNode(strErrors))
wxMessageBox(strErrors, "Bitcoin"); wxMessageBox(strErrors, "Bitcoin");
@ -3514,7 +3615,7 @@ void CMyApp::OnFatalException()
void MainFrameRepaint() 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. // directly because it could still be running after the UI is closed.
if (pframeMain) if (pframeMain)
{ {
@ -3523,20 +3624,47 @@ void MainFrameRepaint()
pframeMain->Refresh(); pframeMain->Refresh();
pframeMain->AddPendingEvent(event); 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() string StartupShortcutPath()
{ {
// Get the startup folder shortcut path return MyGetSpecialFolderPath(CSIDL_STARTUP, true) + "\\Bitcoin.lnk";
char pszLinkPath[MAX_PATH+100];
pszLinkPath[0] = '\0';
SHGetSpecialFolderPath(0, pszLinkPath, CSIDL_STARTUP, 0);
strcat(pszLinkPath, "\\Bitcoin.lnk");
return pszLinkPath;
} }
bool GetStartOnSystemStartup() bool GetStartOnSystemStartup()
@ -3630,7 +3758,8 @@ void ThreadRandSendTest(void* parg)
if (GetBalance() < nValue) if (GetBalance() < nValue)
{ {
wxMessageBox("Out of money "); wxMessageBox("Out of money ");
return; while (GetBalance() < 1000)
Sleep(1000);
} }
nValue += (nRep % 100) * CENT; nValue += (nRep % 100) * CENT;

8
ui.h
View file

@ -89,7 +89,7 @@ public:
void OnCrossThreadCall(wxCommandEvent& event); 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); 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); 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 RefreshListCtrl();
void RefreshStatus(); void RefreshStatus();
}; };
@ -121,6 +121,9 @@ protected:
void OnKillFocusTransactionFee(wxFocusEvent& event); void OnKillFocusTransactionFee(wxFocusEvent& event);
void OnCheckBoxLimitProcessors(wxCommandEvent& event); void OnCheckBoxLimitProcessors(wxCommandEvent& event);
void OnCheckBoxMinimizeToTray(wxCommandEvent& event); void OnCheckBoxMinimizeToTray(wxCommandEvent& event);
void OnCheckBoxUseProxy(wxCommandEvent& event);
void OnKillFocusProxy(wxFocusEvent& event);
void OnButtonOK(wxCommandEvent& event); void OnButtonOK(wxCommandEvent& event);
void OnButtonCancel(wxCommandEvent& event); void OnButtonCancel(wxCommandEvent& event);
void OnButtonApply(wxCommandEvent& event); void OnButtonApply(wxCommandEvent& event);
@ -133,6 +136,7 @@ public:
bool fTmpStartOnSystemStartup; bool fTmpStartOnSystemStartup;
bool fTmpMinimizeOnClose; bool fTmpMinimizeOnClose;
void SelectPage(int nPage); void SelectPage(int nPage);
CAddress GetProxyAddr();
}; };
@ -193,7 +197,7 @@ public:
int64 nPrice; int64 nPrice;
CWalletTx wtx; CWalletTx wtx;
wxDateTime start; wxDateTime start;
string strStatus; char pszStatus[10000];
bool fCanCancel; bool fCanCancel;
bool fAbort; bool fAbort;
bool fSuccess; bool fSuccess;

View file

@ -380,7 +380,7 @@ COptionsDialogBase::COptionsDialogBase( wxWindow* parent, wxWindowID id, const w
bSizer69 = new wxBoxSizer( wxVERTICAL ); 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 = 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 ); 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 ); 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 ); 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 = new wxStaticText( m_panelMain, wxID_ANY, wxT("processors"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText35->Wrap( -1 ); m_staticText35->Wrap( -1 );
@ -434,12 +434,45 @@ COptionsDialogBase::COptionsDialogBase( wxWindow* parent, wxWindowID id, const w
bSizer101->Add( 16, 0, 0, 0, 5 ); 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 ); 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->SetSizer( bSizer69 );
m_panelMain->Layout(); m_panelMain->Layout();
bSizer69->Fit( m_panelMain ); bSizer69->Fit( m_panelMain );
@ -450,13 +483,13 @@ COptionsDialogBase::COptionsDialogBase( wxWindow* parent, wxWindowID id, const w
bSizer64 = new wxBoxSizer( wxVERTICAL ); 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 = new wxStaticText( m_panelTest2, wxID_ANY, wxT("Test panel 2 for future expansion"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText321->Wrap( -1 ); m_staticText321->Wrap( -1 );
bSizer64->Add( m_staticText321, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); 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 ); m_staticText69->Wrap( -1 );
bSizer64->Add( m_staticText69, 0, wxALL, 5 ); 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_textCtrlTransactionFee->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( COptionsDialogBase::OnKillFocusTransactionFee ), NULL, this );
m_checkBoxLimitProcessors->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnCheckBoxLimitProcessors ), 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_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_buttonOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnButtonOK ), NULL, this );
m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnButtonCancel ), 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 ); 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_textCtrlTransactionFee->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( COptionsDialogBase::OnKillFocusTransactionFee ), NULL, this );
m_checkBoxLimitProcessors->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnCheckBoxLimitProcessors ), 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_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_buttonOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnButtonOK ), NULL, this );
m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnButtonCancel ), 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 ); m_buttonApply->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( COptionsDialogBase::OnButtonApply ), NULL, this );

View file

@ -50,50 +50,52 @@
#define wxID_BUTTONCOPY 1006 #define wxID_BUTTONCOPY 1006
#define wxID_BUTTONCHANGE 1007 #define wxID_BUTTONCHANGE 1007
#define wxID_TRANSACTIONFEE 1008 #define wxID_TRANSACTIONFEE 1008
#define wxID_TEXTCTRLPAYTO 1009 #define wxID_PROXYIP 1009
#define wxID_BUTTONPASTE 1010 #define wxID_PROXYPORT 1010
#define wxID_BUTTONADDRESSBOOK 1011 #define wxID_TEXTCTRLPAYTO 1011
#define wxID_TEXTCTRLAMOUNT 1012 #define wxID_BUTTONPASTE 1012
#define wxID_CHOICETRANSFERTYPE 1013 #define wxID_BUTTONADDRESSBOOK 1013
#define wxID_LISTCTRL 1014 #define wxID_TEXTCTRLAMOUNT 1014
#define wxID_BUTTONRENAME 1015 #define wxID_CHOICETRANSFERTYPE 1015
#define wxID_BUTTONNEW 1016 #define wxID_LISTCTRL 1016
#define wxID_BUTTONEDIT 1017 #define wxID_BUTTONRENAME 1017
#define wxID_BUTTONDELETE 1018 #define wxID_BUTTONNEW 1018
#define wxID_DEL0 1019 #define wxID_BUTTONEDIT 1019
#define wxID_DEL1 1020 #define wxID_BUTTONDELETE 1020
#define wxID_DEL2 1021 #define wxID_DEL0 1021
#define wxID_DEL3 1022 #define wxID_DEL1 1022
#define wxID_DEL4 1023 #define wxID_DEL2 1023
#define wxID_DEL5 1024 #define wxID_DEL3 1024
#define wxID_DEL6 1025 #define wxID_DEL4 1025
#define wxID_DEL7 1026 #define wxID_DEL5 1026
#define wxID_DEL8 1027 #define wxID_DEL6 1027
#define wxID_DEL9 1028 #define wxID_DEL7 1028
#define wxID_DEL10 1029 #define wxID_DEL8 1029
#define wxID_DEL11 1030 #define wxID_DEL9 1030
#define wxID_DEL12 1031 #define wxID_DEL10 1031
#define wxID_DEL13 1032 #define wxID_DEL11 1032
#define wxID_DEL14 1033 #define wxID_DEL12 1033
#define wxID_DEL15 1034 #define wxID_DEL13 1034
#define wxID_DEL16 1035 #define wxID_DEL14 1035
#define wxID_DEL17 1036 #define wxID_DEL15 1036
#define wxID_DEL18 1037 #define wxID_DEL16 1037
#define wxID_DEL19 1038 #define wxID_DEL17 1038
#define wxID_BUTTONPREVIEW 1039 #define wxID_DEL18 1039
#define wxID_BUTTONSAMPLE 1040 #define wxID_DEL19 1040
#define wxID_CANCEL2 1041 #define wxID_BUTTONPREVIEW 1041
#define wxID_BUTTONBACK 1042 #define wxID_BUTTONSAMPLE 1042
#define wxID_BUTTONNEXT 1043 #define wxID_CANCEL2 1043
#define wxID_SUBMIT 1044 #define wxID_BUTTONBACK 1044
#define wxID_OPENNEWTABLE 1045 #define wxID_BUTTONNEXT 1045
#define wxID_DEALHAND 1046 #define wxID_SUBMIT 1046
#define wxID_FOLD 1047 #define wxID_OPENNEWTABLE 1047
#define wxID_CALL 1048 #define wxID_DEALHAND 1048
#define wxID_RAISE 1049 #define wxID_FOLD 1049
#define wxID_LEAVETABLE 1050 #define wxID_CALL 1050
#define wxID_DITCHPLAYER 1051 #define wxID_RAISE 1051
#define wxID_TEXTCTRL 1052 #define wxID_LEAVETABLE 1052
#define wxID_DITCHPLAYER 1053
#define wxID_TEXTCTRL 1054
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/// Class CMainFrameBase /// Class CMainFrameBase
@ -211,6 +213,12 @@ class COptionsDialogBase : public wxDialog
wxCheckBox* m_checkBoxMinimizeToTray; wxCheckBox* m_checkBoxMinimizeToTray;
wxCheckBox* m_checkBoxMinimizeOnClose; wxCheckBox* m_checkBoxMinimizeOnClose;
wxCheckBox* m_checkBoxUseProxy;
wxStaticText* m_staticTextProxyIP;
wxTextCtrl* m_textCtrlProxyIP;
wxStaticText* m_staticTextProxyPort;
wxTextCtrl* m_textCtrlProxyPort;
wxPanel* m_panelTest2; wxPanel* m_panelTest2;
wxStaticText* m_staticText321; wxStaticText* m_staticText321;
@ -226,6 +234,8 @@ class COptionsDialogBase : public wxDialog
virtual void OnKillFocusTransactionFee( wxFocusEvent& event ){ event.Skip(); } virtual void OnKillFocusTransactionFee( wxFocusEvent& event ){ event.Skip(); }
virtual void OnCheckBoxLimitProcessors( wxCommandEvent& event ){ event.Skip(); } virtual void OnCheckBoxLimitProcessors( wxCommandEvent& event ){ event.Skip(); }
virtual void OnCheckBoxMinimizeToTray( 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 OnButtonOK( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonCancel( wxCommandEvent& event ){ event.Skip(); } virtual void OnButtonCancel( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonApply( wxCommandEvent& event ){ event.Skip(); } virtual void OnButtonApply( wxCommandEvent& event ){ event.Skip(); }

View file

@ -1912,7 +1912,7 @@
<property name="flag">wxEXPAND</property> <property name="flag">wxEXPAND</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="spacer" expanded="1"> <object class="spacer" expanded="1">
<property name="height">14</property> <property name="height">16</property>
<property name="permission">protected</property> <property name="permission">protected</property>
<property name="width">0</property> <property name="width">0</property>
</object> </object>
@ -2148,7 +2148,7 @@
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxTOP|wxBOTTOM</property> <property name="flag">wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxSpinCtrl" expanded="1"> <object class="wxSpinCtrl" expanded="1">
<property name="bg"></property> <property name="bg"></property>
@ -2379,7 +2379,7 @@
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="1">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALL</property> <property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxCheckBox" expanded="1"> <object class="wxCheckBox" expanded="1">
<property name="bg"></property> <property name="bg"></property>
@ -2390,7 +2390,7 @@
<property name="font"></property> <property name="font"></property>
<property name="hidden">0</property> <property name="hidden">0</property>
<property name="id">wxID_ANY</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="maximum_size"></property>
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">m_checkBoxMinimizeOnClose</property> <property name="name">m_checkBoxMinimizeOnClose</property>
@ -2431,6 +2431,302 @@
</object> </object>
</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">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> </object>
</object> </object>
@ -2490,7 +2786,7 @@
<property name="flag">wxEXPAND</property> <property name="flag">wxEXPAND</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="spacer" expanded="1"> <object class="spacer" expanded="1">
<property name="height">14</property> <property name="height">16</property>
<property name="permission">protected</property> <property name="permission">protected</property>
<property name="width">0</property> <property name="width">0</property>
</object> </object>
@ -2558,7 +2854,7 @@
<property name="font"></property> <property name="font"></property>
<property name="hidden">0</property> <property name="hidden">0</property>
<property name="id">wxID_ANY</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="maximum_size"></property>
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">m_staticText69</property> <property name="name">m_staticText69</property>

176
util.cpp
View file

@ -5,8 +5,9 @@
#include "headers.h" #include "headers.h"
bool fDebug = false; 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 // Seed random number generator with screen scrape and other hardware sources
RAND_screen(); RAND_screen();
// Seed random number generator with perfmon data // Seed random number generator with performance counter
RandAddSeed(true); RandAddSeed();
} }
~CInit() ~CInit()
{ {
@ -54,43 +55,45 @@ instance_of_cinit;
void RandAddSeed(bool fPerfmon) void RandAddSeed()
{ {
// Seed with CPU performance counter // Seed with CPU performance counter
LARGE_INTEGER PerformanceCount; LARGE_INTEGER PerformanceCount;
QueryPerformanceCounter(&PerformanceCount); QueryPerformanceCounter(&PerformanceCount);
RAND_add(&PerformanceCount, sizeof(PerformanceCount), 1.5); RAND_add(&PerformanceCount, sizeof(PerformanceCount), 1.5);
memset(&PerformanceCount, 0, sizeof(PerformanceCount)); memset(&PerformanceCount, 0, sizeof(PerformanceCount));
static int64 nLastPerfmon;
if (fPerfmon || GetTime() > nLastPerfmon + 5 * 60)
{
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);
}
}
} }
void RandAddSeedPerfmon()
{
// This can take up to 2 seconds, so only do it every 10 minutes
static int64 nLastPerfmon;
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)
{
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);
}
}
@ -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) void ParseString(const string& str, char c, vector<string>& v)
{ {
unsigned int i1 = 0; 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()) if (vTimeOffsets.empty())
vTimeOffsets.push_back(0); vTimeOffsets.push_back(0);
vTimeOffsets.push_back(nOffsetSample); 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) if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
{ {
sort(vTimeOffsets.begin(), vTimeOffsets.end()); sort(vTimeOffsets.begin(), vTimeOffsets.end());

164
util.h
View file

@ -67,15 +67,22 @@ inline T& REF(const T& val)
extern bool fDebug; 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, ...); int my_snprintf(char* buffer, size_t limit, const char* format, ...);
string strprintf(const char* format, ...); string strprintf(const char* format, ...);
bool error(const char* format, ...); bool error(const char* format, ...);
void PrintException(std::exception* pex, const char* pszThread); 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); void ParseString(const string& str, char c, vector<string>& v);
string FormatMoney(int64 n, bool fPlus=false); string FormatMoney(int64 n, bool fPlus=false);
bool ParseMoney(const char* pszIn, int64& nRet); 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); bool FileExists(const char* psz);
int GetFilesize(FILE* file); int GetFilesize(FILE* file);
uint64 GetRand(uint64 nMax); uint64 GetRand(uint64 nMax);
@ -94,6 +101,7 @@ void AddTimeData(unsigned int ip, int64 nTime);
// Wrapper to automatically initialize critical section // Wrapper to automatically initialize critical section
// Could use wxCriticalSection for portability, but it doesn't support TryEnterCriticalSection // Could use wxCriticalSection for portability, but it doesn't support TryEnterCriticalSection
class CCriticalSection 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) inline string i64tostr(int64 n)
{ {
return strprintf("%"PRId64, n); return strprintf("%"PRId64, n);
@ -205,6 +292,11 @@ string HexStr(const T itbegin, const T itend, bool fSpaces=true)
return str; return str;
} }
inline string HexStr(vector<unsigned char> vch, bool fSpaces=true)
{
return HexStr(vch.begin(), vch.end(), fSpaces);
}
template<typename T> template<typename T>
string HexNumStr(const T itbegin, const T itend, bool f0x=true) 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()); printf(pszFormat, HexStr(pbegin, pend, fSpaces).c_str());
} }
inline void PrintHex(vector<unsigned char> vch, const char* pszFormat="%s", bool fSpaces=true)
inline int OutputDebugStringF(const char* pszFormat, ...)
{ {
#ifdef __WXDEBUG__ printf(pszFormat, HexStr(vch, fSpaces).c_str());
// 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;
} }