Browse Source

monitor ThreadSocketHandler and terminate and restart if hung, convert _beginthread to CreateThread wrapper, disconnect inactive connections, ping, break up long messages to speed up initial download, better priorities for initiating connections, track how many nodes have requested our blocks and transactions, status #/offline and warning message on unsent blocks, minimize on close as separate option -- linux-test5

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@38 1a98c847-1fd6-4fd8-948a-caf3550aa51b
0.8
s_nakamoto 15 years ago
parent
commit
70e79525c9
  1. 1
      build-unix.txt
  2. 9
      db.cpp
  3. 1
      headers.h
  4. 5
      irc.cpp
  5. 140
      main.cpp
  6. 25
      main.h
  7. 302
      net.cpp
  8. 25
      net.h
  9. 131
      ui.cpp
  10. 2
      ui.h
  11. 16
      uibase.cpp
  12. 92
      uibase.h
  13. 29
      uiproject.fbp
  14. 48
      util.cpp
  15. 105
      util.h

1
build-unix.txt

@ -13,6 +13,7 @@ UNIX BUILD NOTES @@ -13,6 +13,7 @@ UNIX BUILD NOTES
Dependencies
------------
Install the dev files for the shared libraries:
apt-get install build-essential
apt-get install libgtk2.0-dev
apt-get install libssl-dev

9
db.cpp

@ -505,6 +505,13 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet) @@ -505,6 +505,13 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
{
vchDefaultKeyRet.clear();
// Modify defaults
#ifndef __WXMSW__
// Reports that tray icon can disappear on gnome, leaving no way to access the program
fMinimizeToTray = false;
fMinimizeOnClose = false;
#endif
//// todo: shouldn't we catch exceptions and try to recover and continue?
CRITICAL_BLOCK(cs_mapKeys)
CRITICAL_BLOCK(cs_mapWallet)
@ -638,7 +645,7 @@ bool LoadWallet(bool& fFirstRunRet) @@ -638,7 +645,7 @@ bool LoadWallet(bool& fFirstRunRet)
CWalletDB().WriteDefaultKey(keyUser.GetPubKey());
}
_beginthread(ThreadFlushWalletDB, 0, NULL);
CreateThread(ThreadFlushWalletDB, NULL);
return true;
}

1
headers.h

@ -75,7 +75,6 @@ @@ -75,7 +75,6 @@
#include <net/if.h>
#include <ifaddrs.h>
#include <boost/filesystem.hpp>
#include <boost/thread/thread.hpp>
#include <boost/algorithm/string.hpp>
#endif

5
irc.cpp

@ -54,7 +54,7 @@ static bool Send(SOCKET hSocket, const char* pszSend) @@ -54,7 +54,7 @@ static bool Send(SOCKET hSocket, const char* pszSend)
const char* pszEnd = psz + strlen(psz);
while (psz < pszEnd)
{
int ret = send(hSocket, psz, pszEnd - psz, 0);
int ret = send(hSocket, psz, pszEnd - psz, MSG_NOSIGNAL);
if (ret < 0)
return false;
psz += ret;
@ -156,7 +156,7 @@ bool Wait(int nSeconds) @@ -156,7 +156,7 @@ bool Wait(int nSeconds)
void ThreadIRCSeed(void* parg)
{
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
SetThreadPriority(THREAD_PRIORITY_NORMAL);
int nErrorWait = 10;
int nRetryWait = 10;
@ -256,6 +256,7 @@ void ThreadIRCSeed(void* parg) @@ -256,6 +256,7 @@ void ThreadIRCSeed(void* parg)
CAddress addr;
if (DecodeAddress(pszName, addr))
{
addr.nTime = GetAdjustedTime() - 51 * 60;
CAddrDB addrdb;
if (AddAddress(addrdb, addr))
printf("IRC got new address\n");

140
main.cpp

@ -42,6 +42,9 @@ map<uint160, vector<unsigned char> > mapPubKeys; @@ -42,6 +42,9 @@ map<uint160, vector<unsigned char> > mapPubKeys;
CCriticalSection cs_mapKeys;
CKey keyUser;
map<uint256, int> mapRequestCount;
CCriticalSection cs_mapRequestCount;
// Settings
int fGenerateBitcoins = false;
int64 nTransactionFee = 0;
@ -274,7 +277,44 @@ int64 CWalletTx::GetTxTime() const @@ -274,7 +277,44 @@ int64 CWalletTx::GetTxTime() const
return nTimeReceived;
}
int CWalletTx::GetRequestCount() const
{
// Returns -1 if it wasn't being tracked
int nRequests = -1;
CRITICAL_BLOCK(cs_mapRequestCount)
{
if (IsCoinBase())
{
// Generated block
if (hashBlock != 0)
{
map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);
if (mi != mapRequestCount.end())
nRequests = (*mi).second;
}
}
else
{
// Did anyone request this transaction?
map<uint256, int>::iterator mi = mapRequestCount.find(GetHash());
if (mi != mapRequestCount.end())
{
nRequests = (*mi).second;
// How about the block it's in?
if (nRequests == 0 && hashBlock != 0)
{
map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);
if (mi != mapRequestCount.end())
nRequests = (*mi).second;
else
nRequests = 1; // If it's in someone else's block it must have got out
}
}
}
}
return nRequests;
}
@ -295,7 +335,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock) @@ -295,7 +335,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
CTxIndex txindex;
if (!CTxDB("r").ReadTxIndex(GetHash(), txindex))
return 0;
if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, true))
if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos))
return 0;
pblock = &blockTmp;
}
@ -1003,7 +1043,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) @@ -1003,7 +1043,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
foreach(CBlockIndex* pindex, vDisconnect)
{
CBlock block;
if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos, true))
if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos))
return error("Reorganize() : ReadFromDisk for disconnect failed");
if (!block.DisconnectBlock(txdb, pindex))
return error("Reorganize() : DisconnectBlock failed");
@ -1020,7 +1060,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) @@ -1020,7 +1060,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
{
CBlockIndex* pindex = vConnect[i];
CBlock block;
if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos, true))
if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos))
return error("Reorganize() : ReadFromDisk for connect failed");
if (!block.ConnectBlock(txdb, pindex))
{
@ -1380,7 +1420,7 @@ bool CheckDiskSpace(int64 nAdditionalBytes) @@ -1380,7 +1420,7 @@ bool CheckDiskSpace(int64 nAdditionalBytes)
{
fShutdown = true;
ThreadSafeMessageBox("Warning: Your disk space is low ", "Bitcoin", wxOK | wxICON_EXCLAMATION);
_beginthread(Shutdown, 0, NULL);
CreateThread(Shutdown, NULL);
return false;
}
return true;
@ -1547,7 +1587,7 @@ void PrintBlockTree() @@ -1547,7 +1587,7 @@ void PrintBlockTree()
// print item
CBlock block;
block.ReadFromDisk(pindex, true);
block.ReadFromDisk(pindex);
printf("%d (%u,%u) %s %s tx %d",
pindex->nHeight,
pindex->nFile,
@ -1623,6 +1663,7 @@ bool ProcessMessages(CNode* pfrom) @@ -1623,6 +1663,7 @@ bool ProcessMessages(CNode* pfrom)
CDataStream& vRecv = pfrom->vRecv;
if (vRecv.empty())
return true;
//if (fDebug)
// printf("ProcessMessages(%d bytes)\n", vRecv.size());
//
@ -1666,6 +1707,7 @@ bool ProcessMessages(CNode* pfrom) @@ -1666,6 +1707,7 @@ bool ProcessMessages(CNode* pfrom)
{
// Rewind and wait for rest of message
///// need a mechanism to give up waiting for overlong message size error
//if (fDebug)
// printf("message-break\n");
vRecv.insert(vRecv.begin(), BEGIN(hdr), END(hdr));
Sleep(100);
@ -1718,6 +1760,8 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -1718,6 +1760,8 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
static map<unsigned int, vector<unsigned char> > mapReuseKey;
RandAddSeedPerfmon();
if (fDebug)
printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
printf("received: %s (%d bytes)\n", strCommand.c_str(), vRecv.size());
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
{
@ -1739,18 +1783,19 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -1739,18 +1783,19 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CAddress addrMe;
CAddress addrFrom;
uint64 nNonce = 1;
string strSubVer;
vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;
if (pfrom->nVersion >= 106 && !vRecv.empty())
vRecv >> addrFrom >> nNonce;
if (pfrom->nVersion >= 106 && !vRecv.empty())
vRecv >> strSubVer;
if (pfrom->nVersion == 0)
return false;
// Disconnect if we connected to ourself
if (nNonce == nLocalHostNonce)
if (nNonce == nLocalHostNonce && nNonce > 1)
{
pfrom->fDisconnect = true;
pfrom->vRecv.clear();
pfrom->vSend.clear();
return true;
}
@ -1776,10 +1821,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -1776,10 +1821,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->fSuccessfullyConnected = true;
// Update the last seen time
if (pfrom->fNetworkNode)
AddressCurrentlyConnected(pfrom->addr);
printf("version message: version %d\n", pfrom->nVersion);
}
@ -1824,10 +1865,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -1824,10 +1865,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vector<CInv> vInv;
vRecv >> vInv;
// Update the last seen time for this node's address
if (pfrom->fNetworkNode)
AddressCurrentlyConnected(pfrom->addr);
CTxDB txdb("r");
foreach(const CInv& inv, vInv)
{
@ -1842,6 +1879,14 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -1842,6 +1879,14 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->AskFor(inv);
else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), GetOrphanRoot(mapOrphanBlocks[inv.hash]));
// Track requests for our stuff
CRITICAL_BLOCK(cs_mapRequestCount)
{
map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash);
if (mi != mapRequestCount.end())
(*mi).second++;
}
}
}
@ -1879,6 +1924,14 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -1879,6 +1924,14 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->PushMessage(inv.GetCommand(), (*mi).second);
}
}
// Track requests for our stuff
CRITICAL_BLOCK(cs_mapRequestCount)
{
map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash);
if (mi != mapRequestCount.end())
(*mi).second++;
}
}
}
@ -2086,11 +2139,23 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -2086,11 +2139,23 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
}
else if (strCommand == "ping")
{
}
else
{
// Ignore unknown commands for extensibility
}
// Update the last seen time for this node's address
if (pfrom->fNetworkNode)
if (strCommand == "version" || strCommand == "addr" || strCommand == "inv" || strCommand == "getdata" || strCommand == "ping")
AddressCurrentlyConnected(pfrom->addr);
return true;
}
@ -2129,6 +2194,10 @@ bool SendMessages(CNode* pto) @@ -2129,6 +2194,10 @@ bool SendMessages(CNode* pto)
}
}
// Keep-alive ping
if (pto->nLastSend && GetTime() - pto->nLastSend > 12 * 60 && pto->vSend.empty())
pto->PushMessage("ping");
//
// Message: addr
@ -2139,7 +2208,14 @@ bool SendMessages(CNode* pto) @@ -2139,7 +2208,14 @@ bool SendMessages(CNode* pto)
{
// returns true if wasn't already contained in the set
if (pto->setAddrKnown.insert(addr).second)
{
vAddrToSend.push_back(addr);
if (vAddrToSend.size() >= 1000)
{
pto->PushMessage("addr", vAddrToSend);
vAddrToSend.clear();
}
}
}
pto->vAddrToSend.clear();
if (!vAddrToSend.empty())
@ -2157,7 +2233,14 @@ bool SendMessages(CNode* pto) @@ -2157,7 +2233,14 @@ bool SendMessages(CNode* pto)
{
// returns true if wasn't already contained in the set
if (pto->setInventoryKnown.insert(inv).second)
{
vInventoryToSend.push_back(inv);
if (vInventoryToSend.size() >= 1000)
{
pto->PushMessage("inv", vInventoryToSend);
vInventoryToSend.clear();
}
}
}
pto->vInventoryToSend.clear();
pto->setInventoryKnown2.clear();
@ -2179,6 +2262,11 @@ bool SendMessages(CNode* pto) @@ -2179,6 +2262,11 @@ bool SendMessages(CNode* pto)
{
printf("sending getdata: %s\n", inv.ToString().c_str());
vAskFor.push_back(inv);
if (vAskFor.size() >= 1000)
{
pto->PushMessage("getdata", vAskFor);
vAskFor.clear();
}
}
pto->mapAskFor.erase(pto->mapAskFor.begin());
}
@ -2226,8 +2314,8 @@ void GenerateBitcoins(bool fGenerate) @@ -2226,8 +2314,8 @@ void GenerateBitcoins(bool fGenerate)
int nAddThreads = nProcessors - vnThreadsRunning[3];
printf("Starting %d BitcoinMiner threads\n", nAddThreads);
for (int i = 0; i < nAddThreads; i++)
if (_beginthread(ThreadBitcoinMiner, 0, NULL) == -1)
printf("Error: _beginthread(ThreadBitcoinMiner) failed\n");
if (!CreateThread(ThreadBitcoinMiner, NULL))
printf("Error: CreateThread(ThreadBitcoinMiner) failed\n");
}
}
@ -2304,7 +2392,7 @@ void BitcoinMiner() @@ -2304,7 +2392,7 @@ void BitcoinMiner()
CBigNum bnExtraNonce = 0;
while (fGenerateBitcoins)
{
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
SetThreadPriority(THREAD_PRIORITY_LOWEST);
Sleep(50);
if (fShutdown)
return;
@ -2440,7 +2528,7 @@ void BitcoinMiner() @@ -2440,7 +2528,7 @@ void BitcoinMiner()
printf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
pblock->print();
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
SetThreadPriority(THREAD_PRIORITY_NORMAL);
CRITICAL_BLOCK(cs_main)
{
if (pindexPrev == pindexBest)
@ -2450,12 +2538,16 @@ void BitcoinMiner() @@ -2450,12 +2538,16 @@ void BitcoinMiner()
return;
key.MakeNewKey();
// Track how many getdata requests this block gets
CRITICAL_BLOCK(cs_mapRequestCount)
mapRequestCount[pblock->GetHash()] = 0;
// Process this block the same as if we had received it from another node
if (!ProcessBlock(NULL, pblock.release()))
printf("ERROR in BitcoinMiner, ProcessBlock, block not accepted\n");
}
}
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
SetThreadPriority(THREAD_PRIORITY_LOWEST);
Sleep(500);
break;
@ -2534,7 +2626,7 @@ bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet) @@ -2534,7 +2626,7 @@ bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
setCoinsRet.clear();
// List of values less than target
int64 nLowestLarger = _I64_MAX;
int64 nLowestLarger = INT64_MAX;
CWalletTx* pcoinLowestLarger = NULL;
vector<pair<int64, CWalletTx*> > vValue;
int64 nTotalLower = 0;
@ -2777,6 +2869,10 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew) @@ -2777,6 +2869,10 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
return error("SendMoney() : Error finalizing transaction");
}
// Track how many getdata requests our transaction gets
CRITICAL_BLOCK(cs_mapRequestCount)
mapRequestCount[wtxNew.GetHash()] = 0;
printf("SendMoney: %s\n", wtxNew.GetHash().ToString().substr(0,6).c_str());
// Broadcast

25
main.h

@ -34,6 +34,8 @@ extern int nBestHeight; @@ -34,6 +34,8 @@ extern int nBestHeight;
extern uint256 hashBestChain;
extern CBlockIndex* pindexBest;
extern unsigned int nTransactionsUpdated;
extern map<uint256, int> mapRequestCount;
extern CCriticalSection cs_mapRequestCount;
// Settings
extern int fGenerateBitcoins;
@ -647,6 +649,15 @@ public: @@ -647,6 +649,15 @@ public:
nGetCreditCached = 0;
}
IMPLEMENT_SERIALIZE
(
nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);
nVersion = this->nVersion;
READWRITE(hashBlock);
READWRITE(vMerkleBranch);
READWRITE(nIndex);
)
int64 GetCredit(bool fUseCache=false) const
{
// Must wait until coinbase is safely deep enough in the chain before valuing it
@ -661,15 +672,6 @@ public: @@ -661,15 +672,6 @@ public:
return nGetCreditCached;
}
IMPLEMENT_SERIALIZE
(
nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);
nVersion = this->nVersion;
READWRITE(hashBlock);
READWRITE(vMerkleBranch);
READWRITE(nIndex);
)
int SetMerkleBranch(const CBlock* pblock=NULL);
int GetDepthInMainChain() const;
@ -749,6 +751,7 @@ public: @@ -749,6 +751,7 @@ public:
int64 GetTxTime() const;
int GetRequestCount() const;
void AddSupportingTransactions(CTxDB& txdb);
@ -978,7 +981,7 @@ public: @@ -978,7 +981,7 @@ public:
return true;
}
bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions)
bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions=true)
{
SetNull();
@ -1027,7 +1030,7 @@ public: @@ -1027,7 +1030,7 @@ public:
int64 GetBlockValue(int64 nFees) const;
bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);
bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex);
bool ReadFromDisk(const CBlockIndex* blockindex, bool fReadTransactions);
bool ReadFromDisk(const CBlockIndex* blockindex, bool fReadTransactions=true);
bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);
bool CheckBlock() const;
bool AcceptBlock();

302
net.cpp

@ -13,7 +13,6 @@ bool OpenNetworkConnection(const CAddress& addrConnect); @@ -13,7 +13,6 @@ bool OpenNetworkConnection(const CAddress& addrConnect);
//
// Global state variables
//
@ -25,6 +24,7 @@ uint64 nLocalHostNonce = 0; @@ -25,6 +24,7 @@ uint64 nLocalHostNonce = 0;
bool fShutdown = false;
array<int, 10> vnThreadsRunning;
SOCKET hListenSocket = INVALID_SOCKET;
int64 nThreadSocketHandlerHeartbeat = INT64_MAX;
vector<CNode*> vNodes;
CCriticalSection cs_vNodes;
@ -65,7 +65,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet) @@ -65,7 +65,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
if (fProxy)
{
printf("Proxy connecting %s\n", addrConnect.ToStringLog().c_str());
printf("proxy connecting %s\n", addrConnect.ToStringLog().c_str());
char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
@ -87,9 +87,11 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet) @@ -87,9 +87,11 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
if (pchRet[1] != 0x5a)
{
closesocket(hSocket);
return error("Proxy returned error %d", pchRet[1]);
if (pchRet[1] != 0x5b)
printf("ERROR: Proxy returned error %d\n", pchRet[1]);
return false;
}
printf("Proxy connection established %s\n", addrConnect.ToStringLog().c_str());
printf("proxy connected %s\n", addrConnect.ToStringLog().c_str());
}
hSocketRet = hSocket;
@ -219,6 +221,7 @@ bool AddAddress(CAddrDB& addrdb, CAddress addr, bool fCurrentlyOnline) @@ -219,6 +221,7 @@ bool AddAddress(CAddrDB& addrdb, CAddress addr, bool fCurrentlyOnline)
if (it == mapAddresses.end())
{
// New address
printf("AddAddress(%s)\n", addr.ToStringLog().c_str());
mapAddresses.insert(make_pair(addr.GetKey(), addr));
addrdb.WriteAddress(addr);
return true;
@ -256,7 +259,7 @@ void AddressCurrentlyConnected(const CAddress& addr) @@ -256,7 +259,7 @@ void AddressCurrentlyConnected(const CAddress& addr)
if (it != mapAddresses.end())
{
CAddress& addrFound = (*it).second;
int64 nUpdateInterval = 60 * 60;
int64 nUpdateInterval = 20 * 60;
if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval)
{
// Periodically update most recently seen time
@ -417,7 +420,13 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout) @@ -417,7 +420,13 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
}
/// debug print
printf("trying connection %s\n", addrConnect.ToStringLog().c_str());
printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
addrConnect.ToStringLog().c_str(),
(double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
(double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
CRITICAL_BLOCK(cs_mapAddresses)
mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
// Connect
SOCKET hSocket;
@ -445,29 +454,23 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout) @@ -445,29 +454,23 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
CRITICAL_BLOCK(cs_vNodes)
vNodes.push_back(pnode);
CRITICAL_BLOCK(cs_mapAddresses)
mapAddresses[addrConnect.GetKey()].nLastFailed = 0;
pnode->nTimeConnected = GetTime();
return pnode;
}
else
{
CRITICAL_BLOCK(cs_mapAddresses)
mapAddresses[addrConnect.GetKey()].nLastFailed = GetAdjustedTime();
return NULL;
}
}
void CNode::DoDisconnect()
{
if (fDebug)
printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
printf("disconnecting node %s\n", addr.ToStringLog().c_str());
closesocket(hSocket);
// If outbound and never got version message, mark address as failed
if (!fInbound && !fSuccessfullyConnected)
CRITICAL_BLOCK(cs_mapAddresses)
mapAddresses[addr.GetKey()].nLastFailed = GetAdjustedTime();
// All of a nodes broadcasts and subscriptions are automatically torn down
// when it goes down, so a node has to stay up to keep its broadcast going.
@ -508,7 +511,7 @@ void ThreadSocketHandler(void* parg) @@ -508,7 +511,7 @@ void ThreadSocketHandler(void* parg)
PrintException(&e, "ThreadSocketHandler()");
} catch (...) {
vnThreadsRunning[0]--;
PrintException(NULL, "ThreadSocketHandler()");
throw; // support pthread_cancel()
}
printf("ThreadSocketHandler exiting\n");
@ -531,15 +534,18 @@ void ThreadSocketHandler2(void* parg) @@ -531,15 +534,18 @@ void ThreadSocketHandler2(void* parg)
vector<CNode*> vNodesCopy = vNodes;
foreach(CNode* pnode, vNodesCopy)
{
if (pnode->ReadyToDisconnect() && pnode->vRecv.empty() && pnode->vSend.empty())
if (pnode->fDisconnect ||
(pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
{
// remove from vNodes
vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
// close socket
pnode->DoDisconnect();
// hold in disconnected pool until all refs are released
pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 5 * 60);
if (pnode->fNetworkNode)
if (pnode->fNetworkNode || pnode->fInbound)
pnode->Release();
vNodesDisconnected.push_back(pnode);
}
@ -582,8 +588,10 @@ void ThreadSocketHandler2(void* parg) @@ -582,8 +588,10 @@ void ThreadSocketHandler2(void* parg)
fd_set fdsetRecv;
fd_set fdsetSend;
fd_set fdsetError;
FD_ZERO(&fdsetRecv);
FD_ZERO(&fdsetSend);
FD_ZERO(&fdsetError);
SOCKET hSocketMax = 0;
FD_SET(hListenSocket, &fdsetRecv);
hSocketMax = max(hSocketMax, hListenSocket);
@ -592,6 +600,7 @@ void ThreadSocketHandler2(void* parg) @@ -592,6 +600,7 @@ void ThreadSocketHandler2(void* parg)
foreach(CNode* pnode, vNodes)
{
FD_SET(pnode->hSocket, &fdsetRecv);
FD_SET(pnode->hSocket, &fdsetError);
hSocketMax = max(hSocketMax, pnode->hSocket);
TRY_CRITICAL_BLOCK(pnode->cs_vSend)
if (!pnode->vSend.empty())
@ -600,30 +609,21 @@ void ThreadSocketHandler2(void* parg) @@ -600,30 +609,21 @@ void ThreadSocketHandler2(void* parg)
}
vnThreadsRunning[0]--;
int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, NULL, &timeout);
int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
vnThreadsRunning[0]++;
if (fShutdown)
return;
if (nSelect == SOCKET_ERROR)
{
int nErr = WSAGetLastError();
printf("select failed: %d\n", nErr);
printf("socket select error %d\n", nErr);
for (int i = 0; i <= hSocketMax; i++)
{
FD_SET(i, &fdsetRecv);
FD_SET(i, &fdsetSend);
}
FD_ZERO(&fdsetSend);
FD_ZERO(&fdsetError);
Sleep(timeout.tv_usec/1000);
}
//// debug print
//foreach(CNode* pnode, vNodes)
//{
// printf("vRecv = %-5d ", pnode->vRecv.size());
// printf("vSend = %-5d ", pnode->vSend.size());
//}
//printf("\n");
//
// Accept new connections
@ -641,7 +641,7 @@ void ThreadSocketHandler2(void* parg) @@ -641,7 +641,7 @@ void ThreadSocketHandler2(void* parg)
if (hSocket == INVALID_SOCKET)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
printf("ERROR ThreadSocketHandler accept failed: %d\n", WSAGetLastError());
printf("socket error accept failed: %d\n", WSAGetLastError());
}
else
{
@ -669,7 +669,7 @@ void ThreadSocketHandler2(void* parg) @@ -669,7 +669,7 @@ void ThreadSocketHandler2(void* parg)
//
// Receive
//
if (FD_ISSET(hSocket, &fdsetRecv))
if (FD_ISSET(hSocket, &fdsetRecv) || FD_ISSET(hSocket, &fdsetError))
{
TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
{
@ -677,25 +677,29 @@ void ThreadSocketHandler2(void* parg) @@ -677,25 +677,29 @@ void ThreadSocketHandler2(void* parg)
unsigned int nPos = vRecv.size();
// typical socket buffer is 8K-64K
const unsigned int nBufSize = 0x10000;
vRecv.resize(nPos + nBufSize);
int nBytes = recv(hSocket, &vRecv[nPos], nBufSize, 0);
vRecv.resize(nPos + max(nBytes, 0));
if (nBytes == 0)
char pchBuf[0x10000];
int nBytes = recv(hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
if (nBytes > 0)
{
vRecv.resize(nPos + nBytes);
memcpy(&vRecv[nPos], pchBuf, nBytes);
pnode->nLastRecv = GetTime();
}
else if (nBytes == 0)
{
// socket closed gracefully
if (!pnode->fDisconnect)
printf("recv: socket closed\n");
printf("socket closed\n");
pnode->fDisconnect = true;
}
else if (nBytes < 0)
{
// socket error
// error
int nErr = WSAGetLastError();
if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
{
if (!pnode->fDisconnect)
printf("recv failed: %d\n", nErr);
printf("socket recv error %d\n", nErr);
pnode->fDisconnect = true;
}
}
@ -712,28 +716,63 @@ void ThreadSocketHandler2(void* parg) @@ -712,28 +716,63 @@ void ThreadSocketHandler2(void* parg)
CDataStream& vSend = pnode->vSend;
if (!vSend.empty())
{
int nBytes = send(hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL);
int nBytes = send(hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
if (nBytes > 0)
{
vSend.erase(vSend.begin(), vSend.begin() + nBytes);
pnode->nLastSend = GetTime();
}
else if (nBytes == 0)
else if (nBytes < 0)
{
if (pnode->ReadyToDisconnect())
pnode->vSend.clear();
// error
int nErr = WSAGetLastError();
if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
{
printf("socket send error %d\n", nErr);
pnode->fDisconnect = true;
}
else
}
}
}
}
//
// Inactivity checking
//
if (pnode->vSend.empty())
pnode->nLastSendEmpty = GetTime();
if (GetTime() - pnode->nTimeConnected > 60)
{
printf("send error %d\n", nBytes);
if (pnode->ReadyToDisconnect())
pnode->vSend.clear();
if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
{
printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
pnode->fDisconnect = true;
}
else if (GetTime() - pnode->nLastSend > 10 * 60 && GetTime() - pnode->nLastSendEmpty > 10 * 60)
{
printf("socket not sending\n");
pnode->fDisconnect = true;
}
else if (GetTime() - pnode->nLastRecv > (pnode->nVersion >= 107 ? 15*60 : 90*60))
{
printf("socket inactivity timeout\n");
pnode->fDisconnect = true;
}
}
}
//// debug heartbeat
static int64 nHeartbeat1;
if (GetTime() - nHeartbeat1 >= 5 * 60)
{
printf("%s sendrecv\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
nHeartbeat1 = GetTime();
fDebug = true;
}
nThreadSocketHandlerHeartbeat = GetTime();
Sleep(10);
}
}
@ -772,10 +811,14 @@ void ThreadOpenConnections2(void* parg) @@ -772,10 +811,14 @@ void ThreadOpenConnections2(void* parg)
{
printf("ThreadOpenConnections started\n");
// Connect to one specified address
// Connect to specific addresses
while (mapArgs.count("-connect"))
{
OpenNetworkConnection(CAddress(mapArgs["-connect"]));
foreach(string strAddr, mapMultiArgs["-connect"])
{
CAddress addr(strAddr, NODE_NETWORK);
if (addr.IsValid())
OpenNetworkConnection(addr);
for (int i = 0; i < 10; i++)
{
Sleep(1000);
@ -783,6 +826,7 @@ void ThreadOpenConnections2(void* parg) @@ -783,6 +826,7 @@ void ThreadOpenConnections2(void* parg)
return;
}
}
}
// Connect to manually added nodes first
if (mapArgs.count("-addnode"))
@ -821,12 +865,7 @@ void ThreadOpenConnections2(void* parg) @@ -821,12 +865,7 @@ void ThreadOpenConnections2(void* parg)
// Choose an address to connect to based on most recently seen
//
CAddress addrConnect;
int64 nBestTime = 0;
int64 nDelay = ((60 * 60) << vNodes.size());
if (vNodes.size() >= 3)
nDelay *= 4;
if (nGotIRCAddresses > 0)
nDelay *= 100;
int64 nBest = INT64_MIN;
// Do this here so we don't have to critsect vNodes inside mapAddresses critsect
set<unsigned int> setConnected;
@ -841,24 +880,51 @@ void ThreadOpenConnections2(void* parg) @@ -841,24 +880,51 @@ void ThreadOpenConnections2(void* parg)
const CAddress& addr = item.second;
if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip))
continue;
int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;
int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;
// Randomize the order in a deterministic way, putting the standard port first
int64 nRandomizer = (uint64)(addr.nLastFailed * 9567851 + addr.ip * 7789) % (1 * 60 * 60);
int64 nRandomizer = (uint64)(addr.nLastTry * 9567851 + addr.ip * 7789) % (30 * 60);
if (addr.port != DEFAULT_PORT)
nRandomizer += 1 * 60 * 60;
nRandomizer += 30 * 60;
// Last seen Base retry frequency
// <1 hour 10 min
// 1 hour 1 hour
// 4 hours 2 hours
// 24 hours 5 hours
// 48 hours 7 hours
// 7 days 13 hours
// 30 days 27 hours
// 90 days 46 hours
// 365 days 93 hours
int64 nDelay = 3600.0 * sqrt(fabs(nSinceLastSeen) / 3600.0) + nRandomizer;
// Fast reconnect for one hour after last seen
if (nSinceLastSeen < 60 * 60)
nDelay = 10 * 60;
// Limit retry frequency
if (GetAdjustedTime() < addr.nLastFailed + nDelay + nRandomizer)
if (nSinceLastTry < nDelay)
continue;
// Try again only after all addresses had a first attempt
int64 nTime = addr.nTime - nRandomizer;
if (addr.nLastFailed > addr.nTime)
nTime -= 365 * 24 * 60 * 60;
// If we have IRC, we'll be notified when they first come online,
// and again every 24 hours by the refresh broadcast.
if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
continue;
if (nTime > nBestTime)
// Only try the old stuff if we don't have enough connections
if (vNodes.size() >= 2 && nSinceLastSeen > 7 * 24 * 60 * 60)
continue;
if (vNodes.size() >= 4 && nSinceLastSeen > 24 * 60 * 60)
continue;
// If multiple addresses are ready, prioritize by time since
// last seen and time since last tried.
int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
if (nScore > nBest)
{
nBestTime = nTime;
nBest = nScore;
addrConnect = addr;
}
}
@ -941,7 +1007,7 @@ void ThreadMessageHandler(void* parg) @@ -941,7 +1007,7 @@ void ThreadMessageHandler(void* parg)
void ThreadMessageHandler2(void* parg)
{
printf("ThreadMessageHandler started\n");
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
loop
{
// Poll the connected nodes for messages
@ -1063,29 +1129,19 @@ bool BindListenPort(string& strError) @@ -1063,29 +1129,19 @@ bool BindListenPort(string& strError)
return true;
}
bool StartNode(string& strError)
void StartNode(void* parg)
{
strError = "";
if (pnodeLocalHost == NULL)
pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
#ifdef __WXMSW__
// Get local host ip
char pszHostName[255];
if (gethostname(pszHostName, sizeof(pszHostName)) == SOCKET_ERROR)
char pszHostName[1000] = "";
if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
{
strError = strprintf("Error: Unable to get IP address of this computer (gethostname returned error %d)", WSAGetLastError());
printf("%s\n", strError.c_str());
return false;
}
struct hostent* phostent = gethostbyname(pszHostName);
if (!phostent)
if (phostent)
{
strError = strprintf("Error: Unable to get IP address of this computer (gethostbyname returned error %d)", WSAGetLastError());
printf("%s\n", strError.c_str());
return false;
}
// Take the first IP that isn't loopback 127.x.x.x
for (int i = 0; phostent->h_addr_list[i] != NULL; i++)
printf("host ip %d: %s\n", i, CAddress(*(unsigned int*)phostent->h_addr_list[i]).ToStringIP().c_str());
@ -1098,6 +1154,8 @@ bool StartNode(string& strError) @@ -1098,6 +1154,8 @@ bool StartNode(string& strError)
break;
}
}
}
}
#else
// Get local host ip
struct ifaddrs* myaddrs;
@ -1145,45 +1203,85 @@ bool StartNode(string& strError) @@ -1145,45 +1203,85 @@ bool StartNode(string& strError)
}
else
{
if (addrIncoming.ip)
if (addrIncoming.IsValid())
addrLocalHost.ip = addrIncoming.ip;
if (GetMyExternalIP(addrLocalHost.ip))
{
addrIncoming = addrLocalHost;
CWalletDB().WriteSetting("addrIncoming", addrIncoming);
printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
}
}
//
// Start threads
//
// Get addresses from IRC and advertise ours
if (_beginthread(ThreadIRCSeed, 0, NULL) == -1)
printf("Error: _beginthread(ThreadIRCSeed) failed\n");
if (!CreateThread(ThreadIRCSeed, NULL))
printf("Error: CreateThread(ThreadIRCSeed) failed\n");
// Send and receive from sockets, accept connections
pthread_t hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);
// Initiate outbound connections
if (!CreateThread(ThreadOpenConnections, NULL))
printf("Error: CreateThread(ThreadOpenConnections) failed\n");
// Process messages
if (!CreateThread(ThreadMessageHandler, NULL))
printf("Error: CreateThread(ThreadMessageHandler) failed\n");
// Generate coins in the background
GenerateBitcoins(fGenerateBitcoins);
//
// Start threads
// Thread monitoring
//
if (_beginthread(ThreadSocketHandler, 0, NULL) == -1)
loop
{
strError = "Error: _beginthread(ThreadSocketHandler) failed";
printf("%s\n", strError.c_str());
return false;
}
if (_beginthread(ThreadOpenConnections, 0, NULL) == -1)
Sleep(15000);
if (GetTime() - nThreadSocketHandlerHeartbeat > 4 * 60)
{
strError = "Error: _beginthread(ThreadOpenConnections) failed";
printf("%s\n", strError.c_str());
return false;
}
if (_beginthread(ThreadMessageHandler, 0, NULL) == -1)
// First see if closing sockets will free it
printf("*** ThreadSocketHandler is stopped ***\n");
CRITICAL_BLOCK(cs_vNodes)
{
strError = "Error: _beginthread(ThreadMessageHandler) failed";
printf("%s\n", strError.c_str());
return false;
foreach(CNode* pnode, vNodes)
{
bool fGot = false;
TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
TRY_CRITICAL_BLOCK(pnode->cs_vSend)
fGot = true;
if (!fGot)
{
printf("*** closing socket\n");
closesocket(pnode->hSocket);
pnode->fDisconnect = true;
}
}
}
Sleep(10000);
if (GetTime() - nThreadSocketHandlerHeartbeat < 60)
continue;
return true;
// Hopefully it never comes to this.
// We know it'll always be hung in the recv or send call.
// cs_vRecv or cs_vSend may be left permanently unreleased,
// but we always only use TRY_CRITICAL_SECTION on them.
printf("*** Restarting ThreadSocketHandler ***\n");
TerminateThread(hThreadSocketHandler, 0);
#ifdef __WXMSW__
CloseHandle(hThreadSocketHandler);
#endif
vnThreadsRunning[0] = 0;
// Restart
hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);
nThreadSocketHandlerHeartbeat = GetTime();
}
}
}
bool StopNode()

25
net.h

@ -29,7 +29,7 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0); @@ -29,7 +29,7 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
bool AnySubscribed(unsigned int nChannel);
bool BindListenPort(string& strError=REF(string()));
bool StartNode(string& strError=REF(string()));
void StartNode(void* parg);
bool StopNode();
@ -39,7 +39,6 @@ bool StopNode(); @@ -39,7 +39,6 @@ bool StopNode();
//
// Message header
// (4) message start
@ -139,7 +138,7 @@ public: @@ -139,7 +138,7 @@ public:
unsigned int nTime;
// memory only
unsigned int nLastFailed;
unsigned int nLastTry;
CAddress()
{
@ -183,7 +182,7 @@ public: @@ -183,7 +182,7 @@ public:
ip = INADDR_NONE;
port = DEFAULT_PORT;
nTime = GetAdjustedTime();
nLastFailed = 0;
nLastTry = 0;
}
bool SetAddress(const char* pszIn)
@ -458,6 +457,7 @@ extern uint64 nLocalHostNonce; @@ -458,6 +457,7 @@ extern uint64 nLocalHostNonce;
extern bool fShutdown;
extern array<int, 10> vnThreadsRunning;
extern SOCKET hListenSocket;
extern int64 nThreadSocketHandlerHeartbeat;
extern vector<CNode*> vNodes;
extern CCriticalSection cs_vNodes;
@ -486,6 +486,10 @@ public: @@ -486,6 +486,10 @@ public:
CDataStream vRecv;
CCriticalSection cs_vSend;
CCriticalSection cs_vRecv;
int64 nLastSend;
int64 nLastRecv;
int64 nLastSendEmpty;
int64 nTimeConnected;
unsigned int nPushPos;
CAddress addr;
int nVersion;
@ -523,6 +527,10 @@ public: @@ -523,6 +527,10 @@ public:
hSocket = hSocketIn;
vSend.SetType(SER_NETWORK);
vRecv.SetType(SER_NETWORK);
nLastSend = 0;
nLastRecv = 0;
nLastSendEmpty = GetTime();
nTimeConnected = GetTime();
nPushPos = -1;
addr = addrIn;
nVersion = 0;
@ -542,7 +550,7 @@ public: @@ -542,7 +550,7 @@ public:
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);
PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe, nLocalHostNonce, "linux-test5");
}
~CNode()
@ -557,11 +565,6 @@ private: @@ -557,11 +565,6 @@ private:
public:
bool ReadyToDisconnect()
{
return fDisconnect || GetRefCount() <= 0;
}
int GetRefCount()
{
return max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0);
@ -635,6 +638,8 @@ public: @@ -635,6 +638,8 @@ public:
AbortMessage();
nPushPos = vSend.size();
vSend << CMessageHeader(pszCommand, 0);
if (fDebug)
printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
printf("sending: %s ", pszCommand);
}

131
ui.cpp

@ -25,6 +25,7 @@ map<string, string> mapAddressBook; @@ -25,6 +25,7 @@ map<string, string> mapAddressBook;
bool fRandSendTest = false;
void RandSend();
extern int g_isPainting;
bool fClosedToTray = false;
// Settings
int fShowGenerated = true;
@ -413,16 +414,17 @@ void Shutdown(void* parg) @@ -413,16 +414,17 @@ void Shutdown(void* parg)
void CMainFrame::OnClose(wxCloseEvent& event)
{
if (fMinimizeToTray && fMinimizeOnClose && event.CanVeto() && !IsIconized())
if (fMinimizeOnClose && event.CanVeto() && !IsIconized())
{
// Divert close to minimize
event.Veto();
fClosedToTray = true;
Iconize(true);
}
else
{
Destroy();
_beginthread(Shutdown, 0, NULL);
CreateThread(Shutdown, NULL);
}
}
@ -430,7 +432,16 @@ void CMainFrame::OnIconize(wxIconizeEvent& event) @@ -430,7 +432,16 @@ void CMainFrame::OnIconize(wxIconizeEvent& event)
{
// Hide the task bar button when minimized.
// Event is sent when the frame is minimized or restored.
Show(!fMinimizeToTray || !event.Iconized());
if (!event.Iconized())
fClosedToTray = false;
#ifndef __WXMSW__
// Tray is not reliable on Linux gnome
fClosedToTray = false;
#endif
if (fMinimizeToTray && event.Iconized())
fClosedToTray = true;
Show(!fClosedToTray);
ptaskbaricon->Show(fMinimizeToTray || fClosedToTray);
}
void CMainFrame::OnMouseEvents(wxMouseEvent& event)
@ -527,7 +538,6 @@ bool CMainFrame::DeleteLine(uint256 hashKey) @@ -527,7 +538,6 @@ bool CMainFrame::DeleteLine(uint256 hashKey)
string FormatTxStatus(const CWalletTx& wtx)
{
// Status
int nDepth = wtx.GetDepthInMainChain();
if (!wtx.IsFinal())
{
if (wtx.nLockTime < 500000000)
@ -535,11 +545,17 @@ string FormatTxStatus(const CWalletTx& wtx) @@ -535,11 +545,17 @@ string FormatTxStatus(const CWalletTx& wtx)
else
return strprintf("Open until %s", DateTimeStr(wtx.nLockTime).c_str());
}
else
{
int nDepth = wtx.GetDepthInMainChain();
if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
return strprintf("%d/offline?", nDepth);
else if (nDepth < 6)
return strprintf("%d/unconfirmed", nDepth);
else
return strprintf("%d blocks", nDepth);
}
}
string SingleLine(const string& strIn)
{
@ -629,9 +645,17 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) @@ -629,9 +645,17 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
foreach(const CTxOut& txout, wtx.vout)
nUnmatured += txout.GetCredit();
if (wtx.IsInMainChain())
strDescription += strprintf(" (%s matures in %d more blocks)", FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
{
strDescription = strprintf("Generated (%s matures in %d more blocks)", FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
// Check if the block was requested by anyone
if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
strDescription = "Generated - Warning: This block was not received by any other nodes and will probably not be accepted!";
}
else
strDescription += " (not accepted)";
{
strDescription = "Generated (not accepted)";
}
}
}
else if (!mapValue["from"].empty() || !mapValue["message"].empty())
@ -701,8 +725,11 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex) @@ -701,8 +725,11 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
strStatus,
nTime ? DateTimeStr(nTime) : "",
"Payment to yourself",
FormatMoney(nNet - nValue, true),
FormatMoney(nValue, true));
"",
"");
/// issue: can't tell which is the payment and which is the change anymore
// FormatMoney(nNet - nValue, true),
// FormatMoney(nValue, true));
}
else if (fAllFromMe)
{
@ -1028,6 +1055,9 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event) @@ -1028,6 +1055,9 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
string strStatus = strprintf(" %d connections %d blocks %d transactions", vNodes.size(), nBestHeight + 1, nTransactionCount);
m_statusBar->SetStatusText(strStatus, 2);
if (fDebug && GetTime() - nThreadSocketHandlerHeartbeat > 60)
m_statusBar->SetStatusText(" ERROR: ThreadSocketHandler has stopped", 0);
// Pass through to listctrl to actually do the paint, we're just hooking the message
m_listCtrl->Disconnect(wxEVT_PAINT, (wxObjectEventFunction)NULL, NULL, this);
m_listCtrl->GetEventHandler()->ProcessEvent(event);
@ -1237,7 +1267,19 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails @@ -1237,7 +1267,19 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
strHTML += "<b>Status:</b> " + FormatTxStatus(wtx) + "<br>";
strHTML += "<b>Status:</b> " + FormatTxStatus(wtx);
int nRequests = wtx.GetRequestCount();
if (nRequests != -1)
{
if (nRequests == 0)
strHTML += ", has not been successfully broadcast yet";
else if (nRequests == 1)
strHTML += strprintf(", broadcast through %d node", nRequests);
else
strHTML += strprintf(", broadcast through %d nodes", nRequests);
}
strHTML += "<br>";
strHTML += "<b>Date:</b> " + (nTime ? DateTimeStr(nTime) : "") + "<br>";
@ -1366,9 +1408,10 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails @@ -1366,9 +1408,10 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
if (fAllToMe)
{
// Payment to self
int64 nValue = wtx.vout[0].nValue;
strHTML += "<b>Debit:</b> " + FormatMoney(-nValue) + "<br>";
strHTML += "<b>Credit:</b> " + FormatMoney(nValue) + "<br>";
/// issue: can't tell which is the payment and which is the change anymore
//int64 nValue = wtx.vout[0].nValue;
//strHTML += "<b>Debit:</b> " + FormatMoney(-nValue) + "<br>";
//strHTML += "<b>Credit:</b> " + FormatMoney(nValue) + "<br>";
}
int64 nTxFee = nDebit - wtx.GetValueOut();
@ -1469,6 +1512,9 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent) @@ -1469,6 +1512,9 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent)
//m_listBox->Append("Test 2");
m_listBox->SetSelection(0);
SelectPage(0);
#ifndef __WXMSW__
m_checkBoxMinimizeOnClose->SetLabel("&Minimize on close");
#endif
// Init values
m_textCtrlTransactionFee->SetValue(FormatMoney(nTransactionFee));
@ -1481,9 +1527,7 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent) @@ -1481,9 +1527,7 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent)
m_spinCtrlLimitProcessors->SetRange(1, nProcessors);
m_checkBoxStartOnSystemStartup->SetValue(fTmpStartOnSystemStartup = GetStartOnSystemStartup());
m_checkBoxMinimizeToTray->SetValue(fMinimizeToTray);
m_checkBoxMinimizeOnClose->Enable(fMinimizeToTray);
m_checkBoxMinimizeOnClose->SetValue(fMinimizeToTray && fMinimizeOnClose);
fTmpMinimizeOnClose = fMinimizeOnClose;
m_checkBoxMinimizeOnClose->SetValue(fMinimizeOnClose);
m_checkBoxUseProxy->SetValue(fUseProxy);
m_textCtrlProxyIP->Enable(fUseProxy);
m_textCtrlProxyPort->Enable(fUseProxy);
@ -1521,22 +1565,6 @@ void COptionsDialog::OnCheckBoxLimitProcessors(wxCommandEvent& event) @@ -1521,22 +1565,6 @@ void COptionsDialog::OnCheckBoxLimitProcessors(wxCommandEvent& event)
m_spinCtrlLimitProcessors->Enable(event.IsChecked());
}
void COptionsDialog::OnCheckBoxMinimizeToTray(wxCommandEvent& event)
{
m_checkBoxMinimizeOnClose->Enable(event.IsChecked());
// Save the value in fTmpMinimizeOnClose so we can
// show the checkbox unchecked when its parent is unchecked
if (event.IsChecked())
m_checkBoxMinimizeOnClose->SetValue(fTmpMinimizeOnClose);
else
{
fTmpMinimizeOnClose = m_checkBoxMinimizeOnClose->GetValue();
m_checkBoxMinimizeOnClose->SetValue(false);
}
}
void COptionsDialog::OnCheckBoxUseProxy(wxCommandEvent& event)
{
m_textCtrlProxyIP->Enable(event.IsChecked());
@ -1608,12 +1636,12 @@ void COptionsDialog::OnButtonApply(wxCommandEvent& event) @@ -1608,12 +1636,12 @@ void COptionsDialog::OnButtonApply(wxCommandEvent& event)
{
fMinimizeToTray = m_checkBoxMinimizeToTray->GetValue();
walletdb.WriteSetting("fMinimizeToTray", fMinimizeToTray);
ptaskbaricon->Show(fMinimizeToTray);
ptaskbaricon->Show(fMinimizeToTray || fClosedToTray);
}
if (fMinimizeOnClose != (fMinimizeToTray ? m_checkBoxMinimizeOnClose->GetValue() : fTmpMinimizeOnClose))
if (fMinimizeOnClose != m_checkBoxMinimizeOnClose->GetValue())
{
fMinimizeOnClose = (fMinimizeToTray ? m_checkBoxMinimizeOnClose->GetValue() : fTmpMinimizeOnClose);
fMinimizeOnClose = m_checkBoxMinimizeOnClose->GetValue();
walletdb.WriteSetting("fMinimizeOnClose", fMinimizeOnClose);
}
@ -1643,6 +1671,9 @@ CAboutDialog::CAboutDialog(wxWindow* parent) : CAboutDialogBase(parent) @@ -1643,6 +1671,9 @@ CAboutDialog::CAboutDialog(wxWindow* parent) : CAboutDialogBase(parent)
if (str.Find('Â') != wxNOT_FOUND)
str.Remove(str.Find('Â'), 1);
m_staticTextMain->SetLabel(str);
#ifndef __WXMSW__
SetSize(510, 380);
#endif
}
void CAboutDialog::OnButtonOK(wxCommandEvent& event)
@ -1849,7 +1880,7 @@ CSendingDialog::CSendingDialog(wxWindow* parent, const CAddress& addrIn, int64 n @@ -1849,7 +1880,7 @@ CSendingDialog::CSendingDialog(wxWindow* parent, const CAddress& addrIn, int64 n
SetTitle(strprintf("Sending %s to %s", FormatMoney(nPrice).c_str(), wtx.mapValue["to"].c_str()));
m_textCtrlStatus->SetValue("");
_beginthread(SendingDialogStartTransfer, 0, this);
CreateThread(SendingDialogStartTransfer, this);
}
CSendingDialog::~CSendingDialog()
@ -2856,7 +2887,7 @@ CViewProductDialog::CViewProductDialog(wxWindow* parent, const CProduct& product @@ -2856,7 +2887,7 @@ CViewProductDialog::CViewProductDialog(wxWindow* parent, const CProduct& product
this->Layout();
// Request details from seller
_beginthread(ThreadRequestProductDetails, 0, new pair<CProduct, wxEvtHandler*>(product, GetEventHandler()));
CreateThread(ThreadRequestProductDetails, new pair<CProduct, wxEvtHandler*>(product, GetEventHandler()));
}
CViewProductDialog::~CViewProductDialog()
@ -3256,6 +3287,7 @@ void CEditReviewDialog::GetReview(CReview& review) @@ -3256,6 +3287,7 @@ void CEditReviewDialog::GetReview(CReview& review)
enum
{
ID_TASKBAR_RESTORE = 10001,
ID_TASKBAR_OPTIONS,
ID_TASKBAR_GENERATE,
ID_TASKBAR_EXIT,
};
@ -3263,6 +3295,7 @@ enum @@ -3263,6 +3295,7 @@ enum
BEGIN_EVENT_TABLE(CMyTaskBarIcon, wxTaskBarIcon)
EVT_TASKBAR_LEFT_DCLICK(CMyTaskBarIcon::OnLeftButtonDClick)
EVT_MENU(ID_TASKBAR_RESTORE, CMyTaskBarIcon::OnMenuRestore)
EVT_MENU(ID_TASKBAR_OPTIONS, CMyTaskBarIcon::OnMenuOptions)
EVT_MENU(ID_TASKBAR_GENERATE, CMyTaskBarIcon::OnMenuGenerate)
EVT_UPDATE_UI(ID_TASKBAR_GENERATE, CMyTaskBarIcon::OnUpdateUIGenerate)
EVT_MENU(ID_TASKBAR_EXIT, CMyTaskBarIcon::OnMenuExit)
@ -3312,9 +3345,18 @@ void CMyTaskBarIcon::OnMenuRestore(wxCommandEvent& event) @@ -3312,9 +3345,18 @@ void CMyTaskBarIcon::OnMenuRestore(wxCommandEvent& event)
Restore();
}
void CMyTaskBarIcon::OnMenuOptions(wxCommandEvent& event)
{
// Since it's modal, get the main window to do it
wxCommandEvent event2(wxEVT_COMMAND_MENU_SELECTED, wxID_MENUOPTIONSOPTIONS);
pframeMain->AddPendingEvent(event2);
}
void CMyTaskBarIcon::Restore()
{
pframeMain->Show();
wxIconizeEvent event(0, false);
pframeMain->AddPendingEvent(event);
pframeMain->Iconize(false);
pframeMain->Raise();
}
@ -3344,6 +3386,7 @@ wxMenu* CMyTaskBarIcon::CreatePopupMenu() @@ -3344,6 +3386,7 @@ wxMenu* CMyTaskBarIcon::CreatePopupMenu()
{
wxMenu* pmenu = new wxMenu;
pmenu->Append(ID_TASKBAR_RESTORE, "&Open Bitcoin");
pmenu->Append(ID_TASKBAR_OPTIONS, "O&ptions...");
pmenu->AppendCheckItem(ID_TASKBAR_GENERATE, "&Generate Coins")->Check(fGenerateBitcoins);
#ifndef __WXMAC_OSX__ // Mac has built-in quit menu
pmenu->AppendSeparator();
@ -3582,7 +3625,7 @@ bool CMyApp::OnInit2() @@ -3582,7 +3625,7 @@ bool CMyApp::OnInit2()
{
CBlockIndex* pindex = (*mi).second;
CBlock block;
block.ReadFromDisk(pindex, true);
block.ReadFromDisk(pindex);
block.BuildMerkleTree();
block.print();
printf("\n");
@ -3632,20 +3675,20 @@ bool CMyApp::OnInit2() @@ -3632,20 +3675,20 @@ bool CMyApp::OnInit2()
if (mapArgs.count("-min"))
pframeMain->Iconize(true);
pframeMain->Show(true); // have to show first to get taskbar button to hide
pframeMain->Show(!fMinimizeToTray || !pframeMain->IsIconized());
ptaskbaricon->Show(fMinimizeToTray);
if (fMinimizeToTray && pframeMain->IsIconized())
fClosedToTray = true;
pframeMain->Show(!fClosedToTray);
ptaskbaricon->Show(fMinimizeToTray || fClosedToTray);
_beginthread(ThreadDelayedRepaint, 0, NULL);
CreateThread(ThreadDelayedRepaint, NULL);
if (!CheckDiskSpace())
return false;
RandAddSeedPerfmon();
if (!StartNode(strErrors))
wxMessageBox(strErrors, "Bitcoin");
GenerateBitcoins(fGenerateBitcoins);
if (!CreateThread(StartNode, NULL))
wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin");
if (fFirstRun)
SetStartOnSystemStartup(true);

2
ui.h

@ -112,7 +112,6 @@ protected: @@ -112,7 +112,6 @@ protected:
void OnListBox(wxCommandEvent& event);
void OnKillFocusTransactionFee(wxFocusEvent& event);
void OnCheckBoxLimitProcessors(wxCommandEvent& event);
void OnCheckBoxMinimizeToTray(wxCommandEvent& event);
void OnCheckBoxUseProxy(wxCommandEvent& event);
void OnKillFocusProxy(wxFocusEvent& event);
@ -447,6 +446,7 @@ protected: @@ -447,6 +446,7 @@ protected:
// Event handlers
void OnLeftButtonDClick(wxTaskBarIconEvent& event);
void OnMenuRestore(wxCommandEvent& event);
void OnMenuOptions(wxCommandEvent& event);
void OnUpdateUIGenerate(wxUpdateUIEvent& event);
void OnMenuGenerate(wxCommandEvent& event);
void OnMenuExit(wxCommandEvent& event);

16
uibase.cpp

@ -45,7 +45,7 @@ CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString& @@ -45,7 +45,7 @@ CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString&
m_menuOptions->Append( m_menuOptionsChangeYourAddress );
wxMenuItem* m_menuOptionsOptions;
m_menuOptionsOptions = new wxMenuItem( m_menuOptions, wxID_ANY, wxString( wxT("&Options...") ) , wxEmptyString, wxITEM_NORMAL );
m_menuOptionsOptions = new wxMenuItem( m_menuOptions, wxID_MENUOPTIONSOPTIONS, wxString( wxT("&Options...") ) , wxEmptyString, wxITEM_NORMAL );
m_menuOptions->Append( m_menuOptionsOptions );
m_menubar->Append( m_menuOptions, wxT("&Options") );
@ -428,21 +428,13 @@ COptionsDialogBase::COptionsDialogBase( wxWindow* parent, wxWindowID id, const w @@ -428,21 +428,13 @@ COptionsDialogBase::COptionsDialogBase( wxWindow* parent, wxWindowID id, const w
bSizer69->Add( m_checkBoxStartOnSystemStartup, 0, wxALL, 5 );
m_checkBoxMinimizeToTray = new wxCheckBox( m_panelMain, wxID_ANY, wxT("&Minimize to the system tray instead of the taskbar"), wxDefaultPosition, wxDefaultSize, 0 );
m_checkBoxMinimizeToTray = new wxCheckBox( m_panelMain, wxID_ANY, wxT("&Minimize to the tray instead of the taskbar"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer69->Add( m_checkBoxMinimizeToTray, 0, wxALL, 5 );
wxBoxSizer* bSizer101;
bSizer101 = new wxBoxSizer( wxHORIZONTAL );
m_checkBoxMinimizeOnClose = new wxCheckBox( m_panelMain, wxID_ANY, wxT("M&inimize to the tray on close"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer101->Add( 16, 0, 0, 0, 5 );
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|wxALIGN_CENTER_VERTICAL, 5 );
bSizer69->Add( bSizer101, 1, wxEXPAND, 5 );
bSizer69->Add( m_checkBoxMinimizeOnClose, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
wxBoxSizer* bSizer102;
bSizer102 = new wxBoxSizer( wxHORIZONTAL );

92
uibase.h

@ -43,51 +43,52 @@ @@ -43,51 +43,52 @@
#define wxID_MAINFRAME 1000
#define wxID_VIEWSHOWGENERATED 1001
#define wxID_OPTIONSGENERATEBITCOINS 1002
#define wxID_BUTTONSEND 1003
#define wxID_BUTTONRECEIVE 1004
#define wxID_TEXTCTRLADDRESS 1005
#define wxID_BUTTONCOPY 1006
#define wxID_BUTTONCHANGE 1007
#define wxID_TRANSACTIONFEE 1008
#define wxID_PROXYIP 1009
#define wxID_PROXYPORT 1010
#define wxID_TEXTCTRLPAYTO 1011
#define wxID_BUTTONPASTE 1012
#define wxID_BUTTONADDRESSBOOK 1013
#define wxID_TEXTCTRLAMOUNT 1014
#define wxID_CHOICETRANSFERTYPE 1015
#define wxID_LISTCTRL 1016
#define wxID_BUTTONRENAME 1017
#define wxID_BUTTONNEW 1018
#define wxID_BUTTONEDIT 1019
#define wxID_BUTTONDELETE 1020
#define wxID_DEL0 1021
#define wxID_DEL1 1022
#define wxID_DEL2 1023
#define wxID_DEL3 1024
#define wxID_DEL4 1025
#define wxID_DEL5 1026
#define wxID_DEL6 1027
#define wxID_DEL7 1028
#define wxID_DEL8 1029
#define wxID_DEL9 1030
#define wxID_DEL10 1031
#define wxID_DEL11 1032
#define wxID_DEL12 1033
#define wxID_DEL13 1034
#define wxID_DEL14 1035
#define wxID_DEL15 1036
#define wxID_DEL16 1037
#define wxID_DEL17 1038
#define wxID_DEL18 1039
#define wxID_DEL19 1040
#define wxID_BUTTONPREVIEW 1041
#define wxID_BUTTONSAMPLE 1042
#define wxID_CANCEL2 1043
#define wxID_BUTTONBACK 1044
#define wxID_BUTTONNEXT 1045
#define wxID_SUBMIT 1046
#define wxID_TEXTCTRL 1047
#define wxID_MENUOPTIONSOPTIONS 1003
#define wxID_BUTTONSEND 1004
#define wxID_BUTTONRECEIVE 1005
#define wxID_TEXTCTRLADDRESS 1006
#define wxID_BUTTONCOPY 1007
#define wxID_BUTTONCHANGE 1008
#define wxID_TRANSACTIONFEE 1009
#define wxID_PROXYIP 1010
#define wxID_PROXYPORT 1011
#define wxID_TEXTCTRLPAYTO 1012
#define wxID_BUTTONPASTE 1013
#define wxID_BUTTONADDRESSBOOK 1014
#define wxID_TEXTCTRLAMOUNT 1015
#define wxID_CHOICETRANSFERTYPE 1016
#define wxID_LISTCTRL 1017
#define wxID_BUTTONRENAME 1018
#define wxID_BUTTONNEW 1019
#define wxID_BUTTONEDIT 1020
#define wxID_BUTTONDELETE 1021
#define wxID_DEL0 1022
#define wxID_DEL1 1023
#define wxID_DEL2 1024
#define wxID_DEL3 1025
#define wxID_DEL4 1026
#define wxID_DEL5 1027
#define wxID_DEL6 1028
#define wxID_DEL7 1029
#define wxID_DEL8 1030
#define wxID_DEL9 1031
#define wxID_DEL10 1032
#define wxID_DEL11 1033
#define wxID_DEL12 1034
#define wxID_DEL13 1035
#define wxID_DEL14 1036
#define wxID_DEL15 1037
#define wxID_DEL16 1038
#define wxID_DEL17 1039
#define wxID_DEL18 1040
#define wxID_DEL19 1041
#define wxID_BUTTONPREVIEW 1042
#define wxID_BUTTONSAMPLE 1043
#define wxID_CANCEL2 1044
#define wxID_BUTTONBACK 1045
#define wxID_BUTTONNEXT 1046
#define wxID_SUBMIT 1047
#define wxID_TEXTCTRL 1048
///////////////////////////////////////////////////////////////////////////////
/// Class CMainFrameBase
@ -203,7 +204,6 @@ class COptionsDialogBase : public wxDialog @@ -203,7 +204,6 @@ class COptionsDialogBase : public wxDialog
wxStaticText* m_staticText35;
wxCheckBox* m_checkBoxStartOnSystemStartup;
wxCheckBox* m_checkBoxMinimizeToTray;
wxCheckBox* m_checkBoxMinimizeOnClose;
wxCheckBox* m_checkBoxUseProxy;

29
uiproject.fbp

@ -70,7 +70,7 @@ @@ -70,7 +70,7 @@
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
<object class="wxMenuBar" expanded="0">
<object class="wxMenuBar" expanded="1">
<property name="bg">240,240,240</property>
<property name="context_help"></property>
<property name="enabled">1</property>
@ -193,7 +193,7 @@ @@ -193,7 +193,7 @@
<property name="checked">0</property>
<property name="enabled">1</property>
<property name="help"></property>
<property name="id">wxID_ANY</property>
<property name="id">wxID_MENUOPTIONSOPTIONS</property>
<property name="kind">wxITEM_NORMAL</property>
<property name="label">&amp;Options...</property>
<property name="name">m_menuOptionsOptions</property>
@ -2319,7 +2319,7 @@ @@ -2319,7 +2319,7 @@
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">&amp;Minimize to the system tray instead of the taskbar</property>
<property name="label">&amp;Minimize to the tray instead of the taskbar</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">m_checkBoxMinimizeToTray</property>
@ -2358,25 +2358,6 @@ @@ -2358,25 +2358,6 @@
<event name="OnUpdateUI"></event>
</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">bSizer101</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">16</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>
@ -2390,7 +2371,7 @@ @@ -2390,7 +2371,7 @@
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Mi&amp;nimize to system tray on close</property>
<property name="label">M&amp;inimize to the tray on close</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">m_checkBoxMinimizeOnClose</property>
@ -2429,8 +2410,6 @@ @@ -2429,8 +2410,6 @@
<event name="OnUpdateUI"></event>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>

48
util.cpp

@ -85,14 +85,14 @@ void RandAddSeed() @@ -85,14 +85,14 @@ void RandAddSeed()
void RandAddSeedPerfmon()
{
#ifdef __WXMSW__
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
// 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();
#ifdef __WXMSW__
// Don't need this on Linux, OpenSSL automatically uses /dev/urandom
// Seed with the entire set of perfmon data
unsigned char pdata[250000];
memset(pdata, 0, sizeof(pdata));
@ -109,9 +109,30 @@ void RandAddSeedPerfmon() @@ -109,9 +109,30 @@ void RandAddSeedPerfmon()
printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str(), nSize);
}
#else
printf("%s RandAddSeed()\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
#endif
}
uint64 GetRand(uint64 nMax)
{
if (nMax == 0)
return 0;
// The range of the random source must be a multiple of the modulus
// to give every possible output value an equal possibility
uint64 nRange = (UINT64_MAX / nMax) * nMax;
uint64 nRand = 0;
do
RAND_bytes((unsigned char*)&nRand, sizeof(nRand));
while (nRand >= nRange);
return (nRand % nMax);
}
@ -449,28 +470,6 @@ string GetDataDir() @@ -449,28 +470,6 @@ string GetDataDir()
uint64 GetRand(uint64 nMax)
{
if (nMax == 0)
return 0;
// The range of the random source must be a multiple of the modulus
// to give every possible output value an equal possibility
uint64 nRange = (_UI64_MAX / nMax) * nMax;
uint64 nRand = 0;
do
RAND_bytes((unsigned char*)&nRand, sizeof(nRand));
while (nRand >= nRange);
return (nRand % nMax);
}
//
@ -483,7 +482,6 @@ uint64 GetRand(uint64 nMax) @@ -483,7 +482,6 @@ uint64 GetRand(uint64 nMax)
// note: NTP isn't implemented yet, so until then we just use the median
// of other nodes clocks to correct ours.
//
int64 GetTime()
{
return time(NULL);

105
util.h

@ -54,9 +54,13 @@ inline T& REF(const T& val) @@ -54,9 +54,13 @@ inline T& REF(const T& val)
return (T&)val;
}
#ifndef __WXMSW__
#define _UI64_MAX UINT64_MAX
#define _I64_MAX INT64_MAX
#ifdef __WXMSW__
#define MSG_NOSIGNAL 0
#define MSG_DONTWAIT 0
#define UINT64_MAX _UI64_MAX
#define INT64_MAX _I64_MAX
#define INT64_MIN _I64_MIN
#else
#define WSAGetLastError() errno
#define WSAEWOULDBLOCK EWOULDBLOCK
#define WSAEMSGSIZE EMSGSIZE
@ -74,18 +78,6 @@ typedef u_int SOCKET; @@ -74,18 +78,6 @@ typedef u_int SOCKET;
#define MAX_PATH 1024
#define Sleep(n) wxMilliSleep(n)
#define Beep(n1,n2) (0)
inline int _beginthread(void(*pfn)(void*), unsigned nStack, void* parg) { thread(bind(pfn, parg)); return 0; }
inline void _endthread() { pthread_exit(NULL); }
inline int GetCurrentThread() { return 0; }
// threads are processes on linux, so setpriority affects just the one thread
inline void SetThreadPriority(int nThread, int nPriority) { setpriority(PRIO_PROCESS, getpid(), nPriority); }
#define THREAD_PRIORITY_LOWEST PRIO_MIN
#define THREAD_PRIORITY_BELOW_NORMAL 2
#define THREAD_PRIORITY_NORMAL 0
#define THREAD_PRIORITY_ABOVE_NORMAL 0
#endif
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
@ -133,6 +125,7 @@ void AddTimeData(unsigned int ip, int64 nTime); @@ -133,6 +125,7 @@ void AddTimeData(unsigned int ip, int64 nTime);
// Wrapper to automatically initialize critical sections
class CCriticalSection
{
@ -201,8 +194,6 @@ public: @@ -201,8 +194,6 @@ public:
inline int OutputDebugStringF(const char* pszFormat, ...)
{
int ret = 0;
@ -498,3 +489,83 @@ inline uint160 Hash160(const vector<unsigned char>& vch) @@ -498,3 +489,83 @@ inline uint160 Hash160(const vector<unsigned char>& vch)
RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
return hash2;
}
// Note: It turns out we might have been able to use boost::thread
// by using TerminateThread(boost::thread.native_handle(), 0);
#ifdef __WXMSW__
typedef HANDLE pthread_t;
inline pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=false)
{
DWORD nUnused = 0;
HANDLE hthread =
CreateThread(
NULL, // default security
0, // inherit stack size from parent
(LPTHREAD_START_ROUTINE)pfn, // function pointer
parg, // argument
0, // creation option, start immediately
&nUnused); // thread identifier
if (hthread == NULL)
{
printf("Error: CreateThread() returned %d\n", GetLastError());
return (pthread_t)0;
}
if (!fWantHandle)
{
CloseHandle(hthread);
return (pthread_t)-1;
}
return hthread;
}
inline void SetThreadPriority(int nPriority)
{
SetThreadPriority(GetCurrentThread(), nPriority);
}
#else
inline pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=false)
{
pthread_t hthread = 0;
int ret = pthread_create(&hthread, NULL, (void*(*)(void*))pfn, parg);
if (ret != 0)
{
printf("Error: pthread_create() returned %d\n", ret);
return (pthread_t)0;
}
if (!fWantHandle)
return (pthread_t)-1;
return hthread;
}
#define THREAD_PRIORITY_LOWEST PRIO_MIN
#define THREAD_PRIORITY_BELOW_NORMAL 2
#define THREAD_PRIORITY_NORMAL 0
#define THREAD_PRIORITY_ABOVE_NORMAL 0
inline void SetThreadPriority(int nPriority)
{
// threads are processes on linux, so PRIO_PROCESS affects just the one thread
setpriority(PRIO_PROCESS, getpid(), nPriority);
}
inline bool TerminateThread(pthread_t hthread, unsigned int nExitCode)
{
return (pthread_cancel(hthread) == 0);
}
inline void ExitThread(unsigned int nExitCode)
{
pthread_exit((void*)nExitCode);
}
#endif

Loading…
Cancel
Save