aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build-msw.txt2
-rw-r--r--build-unix.txt1
-rw-r--r--db.cpp9
-rw-r--r--headers.h1
-rw-r--r--irc.cpp5
-rw-r--r--main.cpp144
-rw-r--r--main.h25
-rw-r--r--net.cpp342
-rw-r--r--net.h25
-rw-r--r--ui.cpp137
-rw-r--r--ui.h2
-rw-r--r--uibase.cpp16
-rw-r--r--uibase.h92
-rw-r--r--uiproject.fbp121
-rw-r--r--util.cpp48
-rw-r--r--util.h105
16 files changed, 684 insertions, 391 deletions
diff --git a/build-msw.txt b/build-msw.txt
index eb6348bada..a159a71aeb 100644
--- a/build-msw.txt
+++ b/build-msw.txt
@@ -8,7 +8,7 @@ the OpenSSL Toolkit (http://www.openssl.org/). This product includes
cryptographic software written by Eric Young (eay@cryptsoft.com).
- WINDOWS BUILD NOTES
+WINDOWS BUILD NOTES
Compilers Supported
diff --git a/build-unix.txt b/build-unix.txt
index 6b29e1e5c4..ceb61ad545 100644
--- a/build-unix.txt
+++ b/build-unix.txt
@@ -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
diff --git a/db.cpp b/db.cpp
index 61d6025332..a9c42880ab 100644
--- a/db.cpp
+++ b/db.cpp
@@ -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)
CWalletDB().WriteDefaultKey(keyUser.GetPubKey());
}
- _beginthread(ThreadFlushWalletDB, 0, NULL);
+ CreateThread(ThreadFlushWalletDB, NULL);
return true;
}
diff --git a/headers.h b/headers.h
index 76881bb935..22bb830f72 100644
--- a/headers.h
+++ b/headers.h
@@ -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
diff --git a/irc.cpp b/irc.cpp
index 3b232caead..8432c6d145 100644
--- a/irc.cpp
+++ b/irc.cpp
@@ -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)
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)
CAddress addr;
if (DecodeAddress(pszName, addr))
{
+ addr.nTime = GetAdjustedTime() - 51 * 60;
CAddrDB addrdb;
if (AddAddress(addrdb, addr))
printf("IRC got new address\n");
diff --git a/main.cpp b/main.cpp
index b957027f07..13a9f9b72a 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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
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)
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)
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)
{
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)
{
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()
// print item
CBlock block;
- block.ReadFromDisk(pindex, true);
+ block.ReadFromDisk(pindex);
printf("%d (%u,%u) %s %s tx %d",
pindex->nHeight,
pindex->nFile,
@@ -1623,7 +1663,8 @@ bool ProcessMessages(CNode* pfrom)
CDataStream& vRecv = pfrom->vRecv;
if (vRecv.empty())
return true;
- //printf("ProcessMessages(%d bytes)\n", vRecv.size());
+ //if (fDebug)
+ // printf("ProcessMessages(%d bytes)\n", vRecv.size());
//
// Message format
@@ -1666,7 +1707,8 @@ bool ProcessMessages(CNode* pfrom)
{
// Rewind and wait for rest of message
///// need a mechanism to give up waiting for overlong message size error
- //printf("message-break\n");
+ //if (fDebug)
+ // printf("message-break\n");
vRecv.insert(vRecv.begin(), BEGIN(hdr), END(hdr));
Sleep(100);
break;
@@ -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)
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)
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)
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)
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)
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)
}
+ 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)
}
}
+ // 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)
{
// 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)
{
// 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)
{
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)
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()
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()
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()
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)
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)
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
diff --git a/main.h b/main.h
index 853fdfa5b6..8bb1e19e8a 100644
--- a/main.h
+++ b/main.h
@@ -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:
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:
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:
int64 GetTxTime() const;
+ int GetRequestCount() const;
void AddSupportingTransactions(CTxDB& txdb);
@@ -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:
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();
diff --git a/net.cpp b/net.cpp
index 0569604bab..71295d5dee 100644
--- a/net.cpp
+++ b/net.cpp
@@ -13,7 +13,6 @@ bool OpenNetworkConnection(const CAddress& addrConnect);
-
//
// Global state variables
//
@@ -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)
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)
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)
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)
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)
}
/// 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;
@@ -428,7 +437,7 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
// Set to nonblocking
#ifdef __WXMSW__
- u_long nOne = 1;
+ u_long nOne = 1;
if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
#else
@@ -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)
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)
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)
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)
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)
}
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)
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)
//
// 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)
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)
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)
- {
- if (pnode->ReadyToDisconnect())
- pnode->vSend.clear();
- }
- else
+ else if (nBytes < 0)
{
- printf("send error %d\n", nBytes);
- 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;
+ }
}
}
}
}
+
+ //
+ // Inactivity checking
+ //
+ if (pnode->vSend.empty())
+ pnode->nLastSendEmpty = GetTime();
+ if (GetTime() - pnode->nTimeConnected > 60)
+ {
+ 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,15 +811,20 @@ 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"]));
- for (int i = 0; i < 10; i++)
+ foreach(string strAddr, mapMultiArgs["-connect"])
{
- Sleep(1000);
- if (fShutdown)
- return;
+ CAddress addr(strAddr, NODE_NETWORK);
+ if (addr.IsValid())
+ OpenNetworkConnection(addr);
+ for (int i = 0; i < 10; i++)
+ {
+ Sleep(1000);
+ if (fShutdown)
+ return;
+ }
}
}
@@ -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)
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)
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,39 +1129,31 @@ 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)
- {
- 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());
- for (int i = 0; phostent->h_addr_list[i] != NULL; i++)
- {
- CAddress addr(*(unsigned int*)phostent->h_addr_list[i], DEFAULT_PORT, nLocalServices);
- if (addr.IsValid() && addr.GetByte(3) != 127)
+ struct hostent* phostent = gethostbyname(pszHostName);
+ if (phostent)
{
- addrLocalHost = addr;
- break;
+ // 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());
+ for (int i = 0; phostent->h_addr_list[i] != NULL; i++)
+ {
+ CAddress addr(*(unsigned int*)phostent->h_addr_list[i], DEFAULT_PORT, nLocalServices);
+ if (addr.IsValid() && addr.GetByte(3) != 127)
+ {
+ addrLocalHost = addr;
+ break;
+ }
+ }
}
}
#else
@@ -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());
}
}
- // Get addresses from IRC and advertise ours
- if (_beginthread(ThreadIRCSeed, 0, NULL) == -1)
- printf("Error: _beginthread(ThreadIRCSeed) failed\n");
-
//
// Start threads
//
- if (_beginthread(ThreadSocketHandler, 0, NULL) == -1)
- {
- strError = "Error: _beginthread(ThreadSocketHandler) failed";
- printf("%s\n", strError.c_str());
- return false;
- }
- if (_beginthread(ThreadOpenConnections, 0, NULL) == -1)
- {
- strError = "Error: _beginthread(ThreadOpenConnections) failed";
- printf("%s\n", strError.c_str());
- return false;
- }
+ // Get addresses from IRC and advertise ours
+ 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");
- if (_beginthread(ThreadMessageHandler, 0, NULL) == -1)
+ // Generate coins in the background
+ GenerateBitcoins(fGenerateBitcoins);
+
+ //
+ // Thread monitoring
+ //
+ loop
{
- strError = "Error: _beginthread(ThreadMessageHandler) failed";
- printf("%s\n", strError.c_str());
- return false;
+ Sleep(15000);
+ if (GetTime() - nThreadSocketHandlerHeartbeat > 4 * 60)
+ {
+ // First see if closing sockets will free it
+ printf("*** ThreadSocketHandler is stopped ***\n");
+ CRITICAL_BLOCK(cs_vNodes)
+ {
+ 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;
+
+ // 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();
+ }
}
-
- return true;
}
bool StopNode()
diff --git a/net.h b/net.h
index 7b83d462fe..6300d3efcf 100644
--- a/net.h
+++ b/net.h
@@ -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();
-
//
// Message header
// (4) message start
@@ -139,7 +138,7 @@ public:
unsigned int nTime;
// memory only
- unsigned int nLastFailed;
+ unsigned int nLastTry;
CAddress()
{
@@ -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;
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:
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:
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:
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:
public:
- bool ReadyToDisconnect()
- {
- return fDisconnect || GetRefCount() <= 0;
- }
-
int GetRefCount()
{
return max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0);
@@ -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);
}
diff --git a/ui.cpp b/ui.cpp
index e12970b81b..9d7556cb57 100644
--- a/ui.cpp
+++ b/ui.cpp
@@ -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)
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)
{
// 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)
string FormatTxStatus(const CWalletTx& wtx)
{
// Status
- int nDepth = wtx.GetDepthInMainChain();
if (!wtx.IsFinal())
{
if (wtx.nLockTime < 500000000)
@@ -535,10 +545,16 @@ string FormatTxStatus(const CWalletTx& wtx)
else
return strprintf("Open until %s", DateTimeStr(wtx.nLockTime).c_str());
}
- else if (nDepth < 6)
- return strprintf("%d/unconfirmed", nDepth);
else
- return strprintf("%d blocks", nDepth);
+ {
+ 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)
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)
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)
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
- 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
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)
//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)
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)
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)
{
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)
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
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
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)
enum
{
ID_TASKBAR_RESTORE = 10001,
+ ID_TASKBAR_OPTIONS,
ID_TASKBAR_GENERATE,
ID_TASKBAR_EXIT,
};
@@ -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)
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()
{
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()
{
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()
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);
diff --git a/ui.h b/ui.h
index a919c3668d..c4bf8b66f1 100644
--- a/ui.h
+++ b/ui.h
@@ -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:
// 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);
diff --git a/uibase.cpp b/uibase.cpp
index 7bc8081f09..f05f1095fb 100644
--- a/uibase.cpp
+++ b/uibase.cpp
@@ -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
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 );
diff --git a/uibase.h b/uibase.h
index 2cb99e9a59..e0c152185c 100644
--- a/uibase.h
+++ b/uibase.h
@@ -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
wxStaticText* m_staticText35;
wxCheckBox* m_checkBoxStartOnSystemStartup;
wxCheckBox* m_checkBoxMinimizeToTray;
-
wxCheckBox* m_checkBoxMinimizeOnClose;
wxCheckBox* m_checkBoxUseProxy;
diff --git a/uiproject.fbp b/uiproject.fbp
index 3aa1c86bcf..58a99bddd8 100644
--- a/uiproject.fbp
+++ b/uiproject.fbp
@@ -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 @@
<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 @@
<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>
@@ -2360,75 +2360,54 @@
</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="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">M&amp;inimize to the tray on close</property>
+ <property name="maximum_size"></property>
<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>
- <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">Mi&amp;nimize to system tray on close</property>
- <property name="maximum_size"></property>
- <property name="minimum_size"></property>
- <property name="name">m_checkBoxMinimizeOnClose</property>
- <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"></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>
+ <property name="name">m_checkBoxMinimizeOnClose</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"></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">
diff --git a/util.cpp b/util.cpp
index 4a5b983d22..7a947730ce 100644
--- a/util.cpp
+++ b/util.cpp
@@ -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()
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()
-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)
// 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);
diff --git a/util.h b/util.h
index 8fcfcd0dc9..ddac449441 100644
--- a/util.h
+++ b/util.h
@@ -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;
#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);
+
// Wrapper to automatically initialize critical sections
class CCriticalSection
{
@@ -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)
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