monitor ThreadSocketHandler and terminate and restart if hung, convert _beginthread...
authors_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
Fri, 13 Nov 2009 01:23:08 +0000 (01:23 +0000)
committers_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
Fri, 13 Nov 2009 01:23:08 +0000 (01:23 +0000)
16 files changed:
build-msw.txt
build-unix.txt
db.cpp
headers.h
irc.cpp
main.cpp
main.h
net.cpp
net.h
ui.cpp
ui.h
uibase.cpp
uibase.h
uiproject.fbp
util.cpp
util.h

index eb6348b..a159a71 100644 (file)
@@ -8,7 +8,7 @@ the OpenSSL Toolkit (http://www.openssl.org/).  This product includes
 cryptographic software written by Eric Young (eay@cryptsoft.com).\r
 \r
 \r
- WINDOWS BUILD NOTES\r
+WINDOWS BUILD NOTES\r
 \r
 \r
 Compilers Supported\r
index 6b29e1e..ceb61ad 100644 (file)
@@ -13,6 +13,7 @@ UNIX BUILD NOTES
 \r
 Dependencies\r
 ------------\r
+Install the dev files for the shared libraries:\r
 apt-get install build-essential\r
 apt-get install libgtk2.0-dev\r
 apt-get install libssl-dev\r
diff --git a/db.cpp b/db.cpp
index 61d6025..a9c4288 100644 (file)
--- a/db.cpp
+++ b/db.cpp
@@ -505,6 +505,13 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
 {\r
     vchDefaultKeyRet.clear();\r
 \r
+    // Modify defaults\r
+#ifndef __WXMSW__\r
+    // Reports that tray icon can disappear on gnome, leaving no way to access the program\r
+    fMinimizeToTray = false;\r
+    fMinimizeOnClose = false;\r
+#endif\r
+\r
     //// todo: shouldn't we catch exceptions and try to recover and continue?\r
     CRITICAL_BLOCK(cs_mapKeys)\r
     CRITICAL_BLOCK(cs_mapWallet)\r
@@ -638,7 +645,7 @@ bool LoadWallet(bool& fFirstRunRet)
         CWalletDB().WriteDefaultKey(keyUser.GetPubKey());\r
     }\r
 \r
-    _beginthread(ThreadFlushWalletDB, 0, NULL);\r
+    CreateThread(ThreadFlushWalletDB, NULL);\r
     return true;\r
 }\r
 \r
index 76881bb..22bb830 100644 (file)
--- a/headers.h
+++ b/headers.h
@@ -75,7 +75,6 @@
 #include <net/if.h>\r
 #include <ifaddrs.h>\r
 #include <boost/filesystem.hpp>\r
-#include <boost/thread/thread.hpp>\r
 #include <boost/algorithm/string.hpp>\r
 #endif\r
 \r
diff --git a/irc.cpp b/irc.cpp
index 3b232ca..8432c6d 100644 (file)
--- a/irc.cpp
+++ b/irc.cpp
@@ -54,7 +54,7 @@ static bool Send(SOCKET hSocket, const char* pszSend)
     const char* pszEnd = psz + strlen(psz);\r
     while (psz < pszEnd)\r
     {\r
-        int ret = send(hSocket, psz, pszEnd - psz, 0);\r
+        int ret = send(hSocket, psz, pszEnd - psz, MSG_NOSIGNAL);\r
         if (ret < 0)\r
             return false;\r
         psz += ret;\r
@@ -156,7 +156,7 @@ bool Wait(int nSeconds)
 \r
 void ThreadIRCSeed(void* parg)\r
 {\r
-    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);\r
+    SetThreadPriority(THREAD_PRIORITY_NORMAL);\r
     int nErrorWait = 10;\r
     int nRetryWait = 10;\r
 \r
@@ -256,6 +256,7 @@ void ThreadIRCSeed(void* parg)
                 CAddress addr;\r
                 if (DecodeAddress(pszName, addr))\r
                 {\r
+                    addr.nTime = GetAdjustedTime() - 51 * 60;\r
                     CAddrDB addrdb;\r
                     if (AddAddress(addrdb, addr))\r
                         printf("IRC got new address\n");\r
index b957027..13a9f9b 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -42,6 +42,9 @@ map<uint160, vector<unsigned char> > mapPubKeys;
 CCriticalSection cs_mapKeys;\r
 CKey keyUser;\r
 \r
+map<uint256, int> mapRequestCount;\r
+CCriticalSection cs_mapRequestCount;\r
+\r
 // Settings\r
 int fGenerateBitcoins = false;\r
 int64 nTransactionFee = 0;\r
@@ -274,7 +277,44 @@ int64 CWalletTx::GetTxTime() const
     return nTimeReceived;\r
 }\r
 \r
+int CWalletTx::GetRequestCount() const\r
+{\r
+    // Returns -1 if it wasn't being tracked\r
+    int nRequests = -1;\r
+    CRITICAL_BLOCK(cs_mapRequestCount)\r
+    {\r
+        if (IsCoinBase())\r
+        {\r
+            // Generated block\r
+            if (hashBlock != 0)\r
+            {\r
+                map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);\r
+                if (mi != mapRequestCount.end())\r
+                    nRequests = (*mi).second;\r
+            }\r
+        }\r
+        else\r
+        {\r
+            // Did anyone request this transaction?\r
+            map<uint256, int>::iterator mi = mapRequestCount.find(GetHash());\r
+            if (mi != mapRequestCount.end())\r
+            {\r
+                nRequests = (*mi).second;\r
 \r
+                // How about the block it's in?\r
+                if (nRequests == 0 && hashBlock != 0)\r
+                {\r
+                    map<uint256, int>::iterator mi = mapRequestCount.find(hashBlock);\r
+                    if (mi != mapRequestCount.end())\r
+                        nRequests = (*mi).second;\r
+                    else\r
+                        nRequests = 1; // If it's in someone else's block it must have got out\r
+                }\r
+            }\r
+        }\r
+    }\r
+    return nRequests;\r
+}\r
 \r
 \r
 \r
@@ -295,7 +335,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
             CTxIndex txindex;\r
             if (!CTxDB("r").ReadTxIndex(GetHash(), txindex))\r
                 return 0;\r
-            if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, true))\r
+            if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos))\r
                 return 0;\r
             pblock = &blockTmp;\r
         }\r
@@ -1003,7 +1043,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
     foreach(CBlockIndex* pindex, vDisconnect)\r
     {\r
         CBlock block;\r
-        if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos, true))\r
+        if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos))\r
             return error("Reorganize() : ReadFromDisk for disconnect failed");\r
         if (!block.DisconnectBlock(txdb, pindex))\r
             return error("Reorganize() : DisconnectBlock failed");\r
@@ -1020,7 +1060,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
     {\r
         CBlockIndex* pindex = vConnect[i];\r
         CBlock block;\r
-        if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos, true))\r
+        if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos))\r
             return error("Reorganize() : ReadFromDisk for connect failed");\r
         if (!block.ConnectBlock(txdb, pindex))\r
         {\r
@@ -1380,7 +1420,7 @@ bool CheckDiskSpace(int64 nAdditionalBytes)
     {\r
         fShutdown = true;\r
         ThreadSafeMessageBox("Warning: Your disk space is low  ", "Bitcoin", wxOK | wxICON_EXCLAMATION);\r
-        _beginthread(Shutdown, 0, NULL);\r
+        CreateThread(Shutdown, NULL);\r
         return false;\r
     }\r
     return true;\r
@@ -1547,7 +1587,7 @@ void PrintBlockTree()
 \r
         // print item\r
         CBlock block;\r
-        block.ReadFromDisk(pindex, true);\r
+        block.ReadFromDisk(pindex);\r
         printf("%d (%u,%u) %s  %s  tx %d",\r
             pindex->nHeight,\r
             pindex->nFile,\r
@@ -1623,7 +1663,8 @@ bool ProcessMessages(CNode* pfrom)
     CDataStream& vRecv = pfrom->vRecv;\r
     if (vRecv.empty())\r
         return true;\r
-    //printf("ProcessMessages(%d bytes)\n", vRecv.size());\r
+    //if (fDebug)\r
+    //    printf("ProcessMessages(%d bytes)\n", vRecv.size());\r
 \r
     //\r
     // Message format\r
@@ -1666,7 +1707,8 @@ bool ProcessMessages(CNode* pfrom)
         {\r
             // Rewind and wait for rest of message\r
             ///// need a mechanism to give up waiting for overlong message size error\r
-            //printf("message-break\n");\r
+            //if (fDebug)\r
+            //    printf("message-break\n");\r
             vRecv.insert(vRecv.begin(), BEGIN(hdr), END(hdr));\r
             Sleep(100);\r
             break;\r
@@ -1718,6 +1760,8 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
 {\r
     static map<unsigned int, vector<unsigned char> > mapReuseKey;\r
     RandAddSeedPerfmon();\r
+    if (fDebug)\r
+        printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());\r
     printf("received: %s (%d bytes)\n", strCommand.c_str(), vRecv.size());\r
     if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)\r
     {\r
@@ -1739,18 +1783,19 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
         CAddress addrMe;\r
         CAddress addrFrom;\r
         uint64 nNonce = 1;\r
+        string strSubVer;\r
         vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe;\r
         if (pfrom->nVersion >= 106 && !vRecv.empty())\r
             vRecv >> addrFrom >> nNonce;\r
+        if (pfrom->nVersion >= 106 && !vRecv.empty())\r
+            vRecv >> strSubVer;\r
         if (pfrom->nVersion == 0)\r
             return false;\r
 \r
         // Disconnect if we connected to ourself\r
-        if (nNonce == nLocalHostNonce)\r
+        if (nNonce == nLocalHostNonce && nNonce > 1)\r
         {\r
             pfrom->fDisconnect = true;\r
-            pfrom->vRecv.clear();\r
-            pfrom->vSend.clear();\r
             return true;\r
         }\r
 \r
@@ -1776,10 +1821,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
 \r
         pfrom->fSuccessfullyConnected = true;\r
 \r
-        // Update the last seen time\r
-        if (pfrom->fNetworkNode)\r
-            AddressCurrentlyConnected(pfrom->addr);\r
-\r
         printf("version message: version %d\n", pfrom->nVersion);\r
     }\r
 \r
@@ -1824,10 +1865,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
         vector<CInv> vInv;\r
         vRecv >> vInv;\r
 \r
-        // Update the last seen time for this node's address\r
-        if (pfrom->fNetworkNode)\r
-            AddressCurrentlyConnected(pfrom->addr);\r
-\r
         CTxDB txdb("r");\r
         foreach(const CInv& inv, vInv)\r
         {\r
@@ -1842,6 +1879,14 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
                 pfrom->AskFor(inv);\r
             else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))\r
                 pfrom->PushMessage("getblocks", CBlockLocator(pindexBest), GetOrphanRoot(mapOrphanBlocks[inv.hash]));\r
+\r
+            // Track requests for our stuff\r
+            CRITICAL_BLOCK(cs_mapRequestCount)\r
+            {\r
+                map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash);\r
+                if (mi != mapRequestCount.end())\r
+                    (*mi).second++;\r
+            }\r
         }\r
     }\r
 \r
@@ -1879,6 +1924,14 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
                         pfrom->PushMessage(inv.GetCommand(), (*mi).second);\r
                 }\r
             }\r
+\r
+            // Track requests for our stuff\r
+            CRITICAL_BLOCK(cs_mapRequestCount)\r
+            {\r
+                map<uint256, int>::iterator mi = mapRequestCount.find(inv.hash);\r
+                if (mi != mapRequestCount.end())\r
+                    (*mi).second++;\r
+            }\r
         }\r
     }\r
 \r
@@ -2086,11 +2139,23 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
     }\r
 \r
 \r
+    else if (strCommand == "ping")\r
+    {\r
+    }\r
+\r
+\r
     else\r
     {\r
         // Ignore unknown commands for extensibility\r
     }\r
 \r
+\r
+    // Update the last seen time for this node's address\r
+    if (pfrom->fNetworkNode)\r
+        if (strCommand == "version" || strCommand == "addr" || strCommand == "inv" || strCommand == "getdata" || strCommand == "ping")\r
+            AddressCurrentlyConnected(pfrom->addr);\r
+\r
+\r
     return true;\r
 }\r
 \r
@@ -2129,6 +2194,10 @@ bool SendMessages(CNode* pto)
             }\r
         }\r
 \r
+        // Keep-alive ping\r
+        if (pto->nLastSend && GetTime() - pto->nLastSend > 12 * 60 && pto->vSend.empty())\r
+            pto->PushMessage("ping");\r
+\r
 \r
         //\r
         // Message: addr\r
@@ -2139,7 +2208,14 @@ bool SendMessages(CNode* pto)
         {\r
             // returns true if wasn't already contained in the set\r
             if (pto->setAddrKnown.insert(addr).second)\r
+            {\r
                 vAddrToSend.push_back(addr);\r
+                if (vAddrToSend.size() >= 1000)\r
+                {\r
+                    pto->PushMessage("addr", vAddrToSend);\r
+                    vAddrToSend.clear();\r
+                }\r
+            }\r
         }\r
         pto->vAddrToSend.clear();\r
         if (!vAddrToSend.empty())\r
@@ -2157,7 +2233,14 @@ bool SendMessages(CNode* pto)
             {\r
                 // returns true if wasn't already contained in the set\r
                 if (pto->setInventoryKnown.insert(inv).second)\r
+                {\r
                     vInventoryToSend.push_back(inv);\r
+                    if (vInventoryToSend.size() >= 1000)\r
+                    {\r
+                        pto->PushMessage("inv", vInventoryToSend);\r
+                        vInventoryToSend.clear();\r
+                    }\r
+                }\r
             }\r
             pto->vInventoryToSend.clear();\r
             pto->setInventoryKnown2.clear();\r
@@ -2179,6 +2262,11 @@ bool SendMessages(CNode* pto)
             {\r
                 printf("sending getdata: %s\n", inv.ToString().c_str());\r
                 vAskFor.push_back(inv);\r
+                if (vAskFor.size() >= 1000)\r
+                {\r
+                    pto->PushMessage("getdata", vAskFor);\r
+                    vAskFor.clear();\r
+                }\r
             }\r
             pto->mapAskFor.erase(pto->mapAskFor.begin());\r
         }\r
@@ -2226,8 +2314,8 @@ void GenerateBitcoins(bool fGenerate)
         int nAddThreads = nProcessors - vnThreadsRunning[3];\r
         printf("Starting %d BitcoinMiner threads\n", nAddThreads);\r
         for (int i = 0; i < nAddThreads; i++)\r
-            if (_beginthread(ThreadBitcoinMiner, 0, NULL) == -1)\r
-                printf("Error: _beginthread(ThreadBitcoinMiner) failed\n");\r
+            if (!CreateThread(ThreadBitcoinMiner, NULL))\r
+                printf("Error: CreateThread(ThreadBitcoinMiner) failed\n");\r
     }\r
 }\r
 \r
@@ -2304,7 +2392,7 @@ void BitcoinMiner()
     CBigNum bnExtraNonce = 0;\r
     while (fGenerateBitcoins)\r
     {\r
-        SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);\r
+        SetThreadPriority(THREAD_PRIORITY_LOWEST);\r
         Sleep(50);\r
         if (fShutdown)\r
             return;\r
@@ -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());\r
                     pblock->print();\r
 \r
-                SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);\r
+                SetThreadPriority(THREAD_PRIORITY_NORMAL);\r
                 CRITICAL_BLOCK(cs_main)\r
                 {\r
                     if (pindexPrev == pindexBest)\r
@@ -2450,12 +2538,16 @@ void BitcoinMiner()
                             return;\r
                         key.MakeNewKey();\r
 \r
+                        // Track how many getdata requests this block gets\r
+                        CRITICAL_BLOCK(cs_mapRequestCount)\r
+                            mapRequestCount[pblock->GetHash()] = 0;\r
+\r
                         // Process this block the same as if we had received it from another node\r
                         if (!ProcessBlock(NULL, pblock.release()))\r
                             printf("ERROR in BitcoinMiner, ProcessBlock, block not accepted\n");\r
                     }\r
                 }\r
-                SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);\r
+                SetThreadPriority(THREAD_PRIORITY_LOWEST);\r
 \r
                 Sleep(500);\r
                 break;\r
@@ -2534,7 +2626,7 @@ bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet)
     setCoinsRet.clear();\r
 \r
     // List of values less than target\r
-    int64 nLowestLarger = _I64_MAX;\r
+    int64 nLowestLarger = INT64_MAX;\r
     CWalletTx* pcoinLowestLarger = NULL;\r
     vector<pair<int64, CWalletTx*> > vValue;\r
     int64 nTotalLower = 0;\r
@@ -2777,6 +2869,10 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
             return error("SendMoney() : Error finalizing transaction");\r
         }\r
 \r
+        // Track how many getdata requests our transaction gets\r
+        CRITICAL_BLOCK(cs_mapRequestCount)\r
+            mapRequestCount[wtxNew.GetHash()] = 0;\r
+\r
         printf("SendMoney: %s\n", wtxNew.GetHash().ToString().substr(0,6).c_str());\r
 \r
         // Broadcast\r
diff --git a/main.h b/main.h
index 853fdfa..8bb1e19 100644 (file)
--- a/main.h
+++ b/main.h
@@ -34,6 +34,8 @@ extern int nBestHeight;
 extern uint256 hashBestChain;\r
 extern CBlockIndex* pindexBest;\r
 extern unsigned int nTransactionsUpdated;\r
+extern map<uint256, int> mapRequestCount;\r
+extern CCriticalSection cs_mapRequestCount;\r
 \r
 // Settings\r
 extern int fGenerateBitcoins;\r
@@ -647,6 +649,15 @@ public:
         nGetCreditCached = 0;\r
     }\r
 \r
+    IMPLEMENT_SERIALIZE\r
+    (\r
+        nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);\r
+        nVersion = this->nVersion;\r
+        READWRITE(hashBlock);\r
+        READWRITE(vMerkleBranch);\r
+        READWRITE(nIndex);\r
+    )\r
+\r
     int64 GetCredit(bool fUseCache=false) const\r
     {\r
         // Must wait until coinbase is safely deep enough in the chain before valuing it\r
@@ -661,15 +672,6 @@ public:
         return nGetCreditCached;\r
     }\r
 \r
-    IMPLEMENT_SERIALIZE\r
-    (\r
-        nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);\r
-        nVersion = this->nVersion;\r
-        READWRITE(hashBlock);\r
-        READWRITE(vMerkleBranch);\r
-        READWRITE(nIndex);\r
-    )\r
-\r
 \r
     int SetMerkleBranch(const CBlock* pblock=NULL);\r
     int GetDepthInMainChain() const;\r
@@ -749,6 +751,7 @@ public:
 \r
 \r
     int64 GetTxTime() const;\r
+    int GetRequestCount() const;\r
 \r
     void AddSupportingTransactions(CTxDB& txdb);\r
 \r
@@ -978,7 +981,7 @@ public:
         return true;\r
     }\r
 \r
-    bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions)\r
+    bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions=true)\r
     {\r
         SetNull();\r
 \r
@@ -1027,7 +1030,7 @@ public:
     int64 GetBlockValue(int64 nFees) const;\r
     bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);\r
     bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex);\r
-    bool ReadFromDisk(const CBlockIndex* blockindex, bool fReadTransactions);\r
+    bool ReadFromDisk(const CBlockIndex* blockindex, bool fReadTransactions=true);\r
     bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);\r
     bool CheckBlock() const;\r
     bool AcceptBlock();\r
diff --git a/net.cpp b/net.cpp
index 0569604..71295d5 100644 (file)
--- a/net.cpp
+++ b/net.cpp
@@ -13,7 +13,6 @@ bool OpenNetworkConnection(const CAddress& addrConnect);
 \r
 \r
 \r
-\r
 //\r
 // Global state variables\r
 //\r
@@ -25,6 +24,7 @@ uint64 nLocalHostNonce = 0;
 bool fShutdown = false;\r
 array<int, 10> vnThreadsRunning;\r
 SOCKET hListenSocket = INVALID_SOCKET;\r
+int64 nThreadSocketHandlerHeartbeat = INT64_MAX;\r
 \r
 vector<CNode*> vNodes;\r
 CCriticalSection cs_vNodes;\r
@@ -65,7 +65,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
 \r
     if (fProxy)\r
     {\r
-        printf("Proxy connecting %s\n", addrConnect.ToStringLog().c_str());\r
+        printf("proxy connecting %s\n", addrConnect.ToStringLog().c_str());\r
         char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";\r
         memcpy(pszSocks4IP + 2, &addrConnect.port, 2);\r
         memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);\r
@@ -87,9 +87,11 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
         if (pchRet[1] != 0x5a)\r
         {\r
             closesocket(hSocket);\r
-            return error("Proxy returned error %d", pchRet[1]);\r
+            if (pchRet[1] != 0x5b)\r
+                printf("ERROR: Proxy returned error %d\n", pchRet[1]);\r
+            return false;\r
         }\r
-        printf("Proxy connection established %s\n", addrConnect.ToStringLog().c_str());\r
+        printf("proxy connected %s\n", addrConnect.ToStringLog().c_str());\r
     }\r
 \r
     hSocketRet = hSocket;\r
@@ -219,6 +221,7 @@ bool AddAddress(CAddrDB& addrdb, CAddress addr, bool fCurrentlyOnline)
         if (it == mapAddresses.end())\r
         {\r
             // New address\r
+            printf("AddAddress(%s)\n", addr.ToStringLog().c_str());\r
             mapAddresses.insert(make_pair(addr.GetKey(), addr));\r
             addrdb.WriteAddress(addr);\r
             return true;\r
@@ -256,7 +259,7 @@ void AddressCurrentlyConnected(const CAddress& addr)
         if (it != mapAddresses.end())\r
         {\r
             CAddress& addrFound = (*it).second;\r
-            int64 nUpdateInterval = 60 * 60;\r
+            int64 nUpdateInterval = 20 * 60;\r
             if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval)\r
             {\r
                 // Periodically update most recently seen time\r
@@ -417,7 +420,13 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
     }\r
 \r
     /// debug print\r
-    printf("trying connection %s\n", addrConnect.ToStringLog().c_str());\r
+    printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",\r
+        addrConnect.ToStringLog().c_str(),\r
+        (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,\r
+        (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);\r
+\r
+    CRITICAL_BLOCK(cs_mapAddresses)\r
+        mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();\r
 \r
     // Connect\r
     SOCKET hSocket;\r
@@ -428,7 +437,7 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
 \r
         // Set to nonblocking\r
 #ifdef __WXMSW__\r
-               u_long nOne = 1;\r
+        u_long nOne = 1;\r
         if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)\r
             printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());\r
 #else\r
@@ -445,29 +454,23 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
         CRITICAL_BLOCK(cs_vNodes)\r
             vNodes.push_back(pnode);\r
 \r
-        CRITICAL_BLOCK(cs_mapAddresses)\r
-            mapAddresses[addrConnect.GetKey()].nLastFailed = 0;\r
+        pnode->nTimeConnected = GetTime();\r
         return pnode;\r
     }\r
     else\r
     {\r
-        CRITICAL_BLOCK(cs_mapAddresses)\r
-            mapAddresses[addrConnect.GetKey()].nLastFailed = GetAdjustedTime();\r
         return NULL;\r
     }\r
 }\r
 \r
 void CNode::DoDisconnect()\r
 {\r
+    if (fDebug)\r
+        printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());\r
     printf("disconnecting node %s\n", addr.ToStringLog().c_str());\r
 \r
     closesocket(hSocket);\r
 \r
-    // If outbound and never got version message, mark address as failed\r
-    if (!fInbound && !fSuccessfullyConnected)\r
-        CRITICAL_BLOCK(cs_mapAddresses)\r
-            mapAddresses[addr.GetKey()].nLastFailed = GetAdjustedTime();\r
-\r
     // All of a nodes broadcasts and subscriptions are automatically torn down\r
     // when it goes down, so a node has to stay up to keep its broadcast going.\r
 \r
@@ -508,7 +511,7 @@ void ThreadSocketHandler(void* parg)
         PrintException(&e, "ThreadSocketHandler()");\r
     } catch (...) {\r
         vnThreadsRunning[0]--;\r
-        PrintException(NULL, "ThreadSocketHandler()");\r
+        throw; // support pthread_cancel()\r
     }\r
 \r
     printf("ThreadSocketHandler exiting\n");\r
@@ -531,15 +534,18 @@ void ThreadSocketHandler2(void* parg)
             vector<CNode*> vNodesCopy = vNodes;\r
             foreach(CNode* pnode, vNodesCopy)\r
             {\r
-                if (pnode->ReadyToDisconnect() && pnode->vRecv.empty() && pnode->vSend.empty())\r
+                if (pnode->fDisconnect ||\r
+                    (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))\r
                 {\r
                     // remove from vNodes\r
                     vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());\r
+\r
+                    // close socket\r
                     pnode->DoDisconnect();\r
 \r
                     // hold in disconnected pool until all refs are released\r
                     pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 5 * 60);\r
-                    if (pnode->fNetworkNode)\r
+                    if (pnode->fNetworkNode || pnode->fInbound)\r
                         pnode->Release();\r
                     vNodesDisconnected.push_back(pnode);\r
                 }\r
@@ -582,8 +588,10 @@ void ThreadSocketHandler2(void* parg)
 \r
         fd_set fdsetRecv;\r
         fd_set fdsetSend;\r
+        fd_set fdsetError;\r
         FD_ZERO(&fdsetRecv);\r
         FD_ZERO(&fdsetSend);\r
+        FD_ZERO(&fdsetError);\r
         SOCKET hSocketMax = 0;\r
         FD_SET(hListenSocket, &fdsetRecv);\r
         hSocketMax = max(hSocketMax, hListenSocket);\r
@@ -592,6 +600,7 @@ void ThreadSocketHandler2(void* parg)
             foreach(CNode* pnode, vNodes)\r
             {\r
                 FD_SET(pnode->hSocket, &fdsetRecv);\r
+                FD_SET(pnode->hSocket, &fdsetError);\r
                 hSocketMax = max(hSocketMax, pnode->hSocket);\r
                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)\r
                     if (!pnode->vSend.empty())\r
@@ -600,30 +609,21 @@ void ThreadSocketHandler2(void* parg)
         }\r
 \r
         vnThreadsRunning[0]--;\r
-        int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, NULL, &timeout);\r
+        int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);\r
         vnThreadsRunning[0]++;\r
         if (fShutdown)\r
             return;\r
         if (nSelect == SOCKET_ERROR)\r
         {\r
             int nErr = WSAGetLastError();\r
-            printf("select failed: %d\n", nErr);\r
+            printf("socket select error %d\n", nErr);\r
             for (int i = 0; i <= hSocketMax; i++)\r
-            {\r
                 FD_SET(i, &fdsetRecv);\r
-                FD_SET(i, &fdsetSend);\r
-            }\r
+            FD_ZERO(&fdsetSend);\r
+            FD_ZERO(&fdsetError);\r
             Sleep(timeout.tv_usec/1000);\r
         }\r
 \r
-        //// debug print\r
-        //foreach(CNode* pnode, vNodes)\r
-        //{\r
-        //    printf("vRecv = %-5d ", pnode->vRecv.size());\r
-        //    printf("vSend = %-5d    ", pnode->vSend.size());\r
-        //}\r
-        //printf("\n");\r
-\r
 \r
         //\r
         // Accept new connections\r
@@ -641,7 +641,7 @@ void ThreadSocketHandler2(void* parg)
             if (hSocket == INVALID_SOCKET)\r
             {\r
                 if (WSAGetLastError() != WSAEWOULDBLOCK)\r
-                    printf("ERROR ThreadSocketHandler accept failed: %d\n", WSAGetLastError());\r
+                    printf("socket error accept failed: %d\n", WSAGetLastError());\r
             }\r
             else\r
             {\r
@@ -669,7 +669,7 @@ void ThreadSocketHandler2(void* parg)
             //\r
             // Receive\r
             //\r
-            if (FD_ISSET(hSocket, &fdsetRecv))\r
+            if (FD_ISSET(hSocket, &fdsetRecv) || FD_ISSET(hSocket, &fdsetError))\r
             {\r
                 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)\r
                 {\r
@@ -677,25 +677,29 @@ void ThreadSocketHandler2(void* parg)
                     unsigned int nPos = vRecv.size();\r
 \r
                     // typical socket buffer is 8K-64K\r
-                    const unsigned int nBufSize = 0x10000;\r
-                    vRecv.resize(nPos + nBufSize);\r
-                    int nBytes = recv(hSocket, &vRecv[nPos], nBufSize, 0);\r
-                    vRecv.resize(nPos + max(nBytes, 0));\r
-                    if (nBytes == 0)\r
+                    char pchBuf[0x10000];\r
+                    int nBytes = recv(hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);\r
+                    if (nBytes > 0)\r
+                    {\r
+                        vRecv.resize(nPos + nBytes);\r
+                        memcpy(&vRecv[nPos], pchBuf, nBytes);\r
+                        pnode->nLastRecv = GetTime();\r
+                    }\r
+                    else if (nBytes == 0)\r
                     {\r
                         // socket closed gracefully\r
                         if (!pnode->fDisconnect)\r
-                            printf("recv: socket closed\n");\r
+                            printf("socket closed\n");\r
                         pnode->fDisconnect = true;\r
                     }\r
                     else if (nBytes < 0)\r
                     {\r
-                        // socket error\r
+                        // error\r
                         int nErr = WSAGetLastError();\r
                         if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)\r
                         {\r
                             if (!pnode->fDisconnect)\r
-                                printf("recv failed: %d\n", nErr);\r
+                                printf("socket recv error %d\n", nErr);\r
                             pnode->fDisconnect = true;\r
                         }\r
                     }\r
@@ -712,28 +716,63 @@ void ThreadSocketHandler2(void* parg)
                     CDataStream& vSend = pnode->vSend;\r
                     if (!vSend.empty())\r
                     {\r
-                        int nBytes = send(hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL);\r
+                        int nBytes = send(hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);\r
                         if (nBytes > 0)\r
                         {\r
                             vSend.erase(vSend.begin(), vSend.begin() + nBytes);\r
+                            pnode->nLastSend = GetTime();\r
                         }\r
-                        else if (nBytes == 0)\r
-                        {\r
-                            if (pnode->ReadyToDisconnect())\r
-                                pnode->vSend.clear();\r
-                        }\r
-                        else\r
+                        else if (nBytes < 0)\r
                         {\r
-                            printf("send error %d\n", nBytes);\r
-                            if (pnode->ReadyToDisconnect())\r
-                                pnode->vSend.clear();\r
+                            // error\r
+                            int nErr = WSAGetLastError();\r
+                            if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)\r
+                            {\r
+                                printf("socket send error %d\n", nErr);\r
+                                pnode->fDisconnect = true;\r
+                            }\r
                         }\r
                     }\r
                 }\r
             }\r
+\r
+            //\r
+            // Inactivity checking\r
+            //\r
+            if (pnode->vSend.empty())\r
+                pnode->nLastSendEmpty = GetTime();\r
+            if (GetTime() - pnode->nTimeConnected > 60)\r
+            {\r
+                if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)\r
+                {\r
+                    printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);\r
+                    pnode->fDisconnect = true;\r
+                }\r
+                else if (GetTime() - pnode->nLastSend > 10 * 60 && GetTime() - pnode->nLastSendEmpty > 10 * 60)\r
+                {\r
+                    printf("socket not sending\n");\r
+                    pnode->fDisconnect = true;\r
+                }\r
+                else if (GetTime() - pnode->nLastRecv > (pnode->nVersion >= 107 ? 15*60 : 90*60))\r
+                {\r
+                    printf("socket inactivity timeout\n");\r
+                    pnode->fDisconnect = true;\r
+                }\r
+            }\r
+        }\r
+\r
+\r
+        //// debug heartbeat\r
+        static int64 nHeartbeat1;\r
+        if (GetTime() - nHeartbeat1 >= 5 * 60)\r
+        {\r
+            printf("%s sendrecv\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());\r
+            nHeartbeat1 = GetTime();\r
+            fDebug = true;\r
         }\r
 \r
 \r
+        nThreadSocketHandlerHeartbeat = GetTime();\r
         Sleep(10);\r
     }\r
 }\r
@@ -772,15 +811,20 @@ void ThreadOpenConnections2(void* parg)
 {\r
     printf("ThreadOpenConnections started\n");\r
 \r
-    // Connect to one specified address\r
+    // Connect to specific addresses\r
     while (mapArgs.count("-connect"))\r
     {\r
-        OpenNetworkConnection(CAddress(mapArgs["-connect"]));\r
-        for (int i = 0; i < 10; i++)\r
+        foreach(string strAddr, mapMultiArgs["-connect"])\r
         {\r
-            Sleep(1000);\r
-            if (fShutdown)\r
-                return;\r
+            CAddress addr(strAddr, NODE_NETWORK);\r
+            if (addr.IsValid())\r
+                OpenNetworkConnection(addr);\r
+            for (int i = 0; i < 10; i++)\r
+            {\r
+                Sleep(1000);\r
+                if (fShutdown)\r
+                    return;\r
+            }\r
         }\r
     }\r
 \r
@@ -821,12 +865,7 @@ void ThreadOpenConnections2(void* parg)
         // Choose an address to connect to based on most recently seen\r
         //\r
         CAddress addrConnect;\r
-        int64 nBestTime = 0;\r
-        int64 nDelay = ((60 * 60) << vNodes.size());\r
-        if (vNodes.size() >= 3)\r
-            nDelay *= 4;\r
-        if (nGotIRCAddresses > 0)\r
-            nDelay *= 100;\r
+        int64 nBest = INT64_MIN;\r
 \r
         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect\r
         set<unsigned int> setConnected;\r
@@ -841,24 +880,51 @@ void ThreadOpenConnections2(void* parg)
                 const CAddress& addr = item.second;\r
                 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip))\r
                     continue;\r
+                int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;\r
+                int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;\r
 \r
                 // Randomize the order in a deterministic way, putting the standard port first\r
-                int64 nRandomizer = (uint64)(addr.nLastFailed * 9567851 + addr.ip * 7789) % (1 * 60 * 60);\r
+                int64 nRandomizer = (uint64)(addr.nLastTry * 9567851 + addr.ip * 7789) % (30 * 60);\r
                 if (addr.port != DEFAULT_PORT)\r
-                    nRandomizer += 1 * 60 * 60;\r
+                    nRandomizer += 30 * 60;\r
+\r
+                // Last seen  Base retry frequency\r
+                //   <1 hour   10 min\r
+                //    1 hour    1 hour\r
+                //    4 hours   2 hours\r
+                //   24 hours   5 hours\r
+                //   48 hours   7 hours\r
+                //    7 days   13 hours\r
+                //   30 days   27 hours\r
+                //   90 days   46 hours\r
+                //  365 days   93 hours\r
+                int64 nDelay = 3600.0 * sqrt(fabs(nSinceLastSeen) / 3600.0) + nRandomizer;\r
+\r
+                // Fast reconnect for one hour after last seen\r
+                if (nSinceLastSeen < 60 * 60)\r
+                    nDelay = 10 * 60;\r
 \r
                 // Limit retry frequency\r
-                if (GetAdjustedTime() < addr.nLastFailed + nDelay + nRandomizer)\r
+                if (nSinceLastTry < nDelay)\r
                     continue;\r
 \r
-                // Try again only after all addresses had a first attempt\r
-                int64 nTime = addr.nTime - nRandomizer;\r
-                if (addr.nLastFailed > addr.nTime)\r
-                    nTime -= 365 * 24 * 60 * 60;\r
+                // If we have IRC, we'll be notified when they first come online,\r
+                // and again every 24 hours by the refresh broadcast.\r
+                if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)\r
+                    continue;\r
 \r
-                if (nTime > nBestTime)\r
+                // Only try the old stuff if we don't have enough connections\r
+                if (vNodes.size() >= 2 && nSinceLastSeen > 7 * 24 * 60 * 60)\r
+                    continue;\r
+                if (vNodes.size() >= 4 && nSinceLastSeen > 24 * 60 * 60)\r
+                    continue;\r
+\r
+                // If multiple addresses are ready, prioritize by time since\r
+                // last seen and time since last tried.\r
+                int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;\r
+                if (nScore > nBest)\r
                 {\r
-                    nBestTime = nTime;\r
+                    nBest = nScore;\r
                     addrConnect = addr;\r
                 }\r
             }\r
@@ -941,7 +1007,7 @@ void ThreadMessageHandler(void* parg)
 void ThreadMessageHandler2(void* parg)\r
 {\r
     printf("ThreadMessageHandler started\n");\r
-    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);\r
+    SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);\r
     loop\r
     {\r
         // Poll the connected nodes for messages\r
@@ -1063,39 +1129,31 @@ bool BindListenPort(string& strError)
     return true;\r
 }\r
 \r
-bool StartNode(string& strError)\r
+void StartNode(void* parg)\r
 {\r
-    strError = "";\r
     if (pnodeLocalHost == NULL)\r
         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));\r
 \r
 #ifdef __WXMSW__\r
     // Get local host ip\r
-    char pszHostName[255];\r
-    if (gethostname(pszHostName, sizeof(pszHostName)) == SOCKET_ERROR)\r
+    char pszHostName[1000] = "";\r
+    if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)\r
     {\r
-        strError = strprintf("Error: Unable to get IP address of this computer (gethostname returned error %d)", WSAGetLastError());\r
-        printf("%s\n", strError.c_str());\r
-        return false;\r
-    }\r
-    struct hostent* phostent = gethostbyname(pszHostName);\r
-    if (!phostent)\r
-    {\r
-        strError = strprintf("Error: Unable to get IP address of this computer (gethostbyname returned error %d)", WSAGetLastError());\r
-        printf("%s\n", strError.c_str());\r
-        return false;\r
-    }\r
-\r
-    // Take the first IP that isn't loopback 127.x.x.x\r
-    for (int i = 0; phostent->h_addr_list[i] != NULL; i++)\r
-        printf("host ip %d: %s\n", i, CAddress(*(unsigned int*)phostent->h_addr_list[i]).ToStringIP().c_str());\r
-    for (int i = 0; phostent->h_addr_list[i] != NULL; i++)\r
-    {\r
-        CAddress addr(*(unsigned int*)phostent->h_addr_list[i], DEFAULT_PORT, nLocalServices);\r
-        if (addr.IsValid() && addr.GetByte(3) != 127)\r
+        struct hostent* phostent = gethostbyname(pszHostName);\r
+        if (phostent)\r
         {\r
-            addrLocalHost = addr;\r
-            break;\r
+            // Take the first IP that isn't loopback 127.x.x.x\r
+            for (int i = 0; phostent->h_addr_list[i] != NULL; i++)\r
+                printf("host ip %d: %s\n", i, CAddress(*(unsigned int*)phostent->h_addr_list[i]).ToStringIP().c_str());\r
+            for (int i = 0; phostent->h_addr_list[i] != NULL; i++)\r
+            {\r
+                CAddress addr(*(unsigned int*)phostent->h_addr_list[i], DEFAULT_PORT, nLocalServices);\r
+                if (addr.IsValid() && addr.GetByte(3) != 127)\r
+                {\r
+                    addrLocalHost = addr;\r
+                    break;\r
+                }\r
+            }\r
         }\r
     }\r
 #else\r
@@ -1145,45 +1203,85 @@ bool StartNode(string& strError)
     }\r
     else\r
     {\r
-        if (addrIncoming.ip)\r
+        if (addrIncoming.IsValid())\r
             addrLocalHost.ip = addrIncoming.ip;\r
 \r
         if (GetMyExternalIP(addrLocalHost.ip))\r
         {\r
             addrIncoming = addrLocalHost;\r
             CWalletDB().WriteSetting("addrIncoming", addrIncoming);\r
+            printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());\r
         }\r
     }\r
 \r
-    // Get addresses from IRC and advertise ours\r
-    if (_beginthread(ThreadIRCSeed, 0, NULL) == -1)\r
-        printf("Error: _beginthread(ThreadIRCSeed) failed\n");\r
-\r
     //\r
     // Start threads\r
     //\r
-    if (_beginthread(ThreadSocketHandler, 0, NULL) == -1)\r
-    {\r
-        strError = "Error: _beginthread(ThreadSocketHandler) failed";\r
-        printf("%s\n", strError.c_str());\r
-        return false;\r
-    }\r
 \r
-    if (_beginthread(ThreadOpenConnections, 0, NULL) == -1)\r
-    {\r
-        strError = "Error: _beginthread(ThreadOpenConnections) failed";\r
-        printf("%s\n", strError.c_str());\r
-        return false;\r
-    }\r
+    // Get addresses from IRC and advertise ours\r
+    if (!CreateThread(ThreadIRCSeed, NULL))\r
+        printf("Error: CreateThread(ThreadIRCSeed) failed\n");\r
+\r
+    // Send and receive from sockets, accept connections\r
+    pthread_t hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);\r
+\r
+    // Initiate outbound connections\r
+    if (!CreateThread(ThreadOpenConnections, NULL))\r
+        printf("Error: CreateThread(ThreadOpenConnections) failed\n");\r
+\r
+    // Process messages\r
+    if (!CreateThread(ThreadMessageHandler, NULL))\r
+        printf("Error: CreateThread(ThreadMessageHandler) failed\n");\r
 \r
-    if (_beginthread(ThreadMessageHandler, 0, NULL) == -1)\r
+    // Generate coins in the background\r
+    GenerateBitcoins(fGenerateBitcoins);\r
+\r
+    //\r
+    // Thread monitoring\r
+    //\r
+    loop\r
     {\r
-        strError = "Error: _beginthread(ThreadMessageHandler) failed";\r
-        printf("%s\n", strError.c_str());\r
-        return false;\r
+        Sleep(15000);\r
+        if (GetTime() - nThreadSocketHandlerHeartbeat > 4 * 60)\r
+        {\r
+            // First see if closing sockets will free it\r
+            printf("*** ThreadSocketHandler is stopped ***\n");\r
+            CRITICAL_BLOCK(cs_vNodes)\r
+            {\r
+                foreach(CNode* pnode, vNodes)\r
+                {\r
+                    bool fGot = false;\r
+                    TRY_CRITICAL_BLOCK(pnode->cs_vRecv)\r
+                        TRY_CRITICAL_BLOCK(pnode->cs_vSend)\r
+                            fGot = true;\r
+                    if (!fGot)\r
+                    {\r
+                        printf("*** closing socket\n");\r
+                        closesocket(pnode->hSocket);\r
+                        pnode->fDisconnect = true;\r
+                    }\r
+                }\r
+            }\r
+            Sleep(10000);\r
+            if (GetTime() - nThreadSocketHandlerHeartbeat < 60)\r
+                continue;\r
+\r
+            // Hopefully it never comes to this.\r
+            // We know it'll always be hung in the recv or send call.\r
+            // cs_vRecv or cs_vSend may be left permanently unreleased,\r
+            // but we always only use TRY_CRITICAL_SECTION on them.\r
+            printf("*** Restarting ThreadSocketHandler ***\n");\r
+            TerminateThread(hThreadSocketHandler, 0);\r
+            #ifdef __WXMSW__\r
+            CloseHandle(hThreadSocketHandler);\r
+            #endif\r
+            vnThreadsRunning[0] = 0;\r
+\r
+            // Restart\r
+            hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);\r
+            nThreadSocketHandlerHeartbeat = GetTime();\r
+        }\r
     }\r
-\r
-    return true;\r
 }\r
 \r
 bool StopNode()\r
diff --git a/net.h b/net.h
index 7b83d46..6300d3e 100644 (file)
--- 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);\r
 bool AnySubscribed(unsigned int nChannel);\r
 bool BindListenPort(string& strError=REF(string()));\r
-bool StartNode(string& strError=REF(string()));\r
+void StartNode(void* parg);\r
 bool StopNode();\r
 \r
 \r
@@ -39,7 +39,6 @@ bool StopNode();
 \r
 \r
 \r
-\r
 //\r
 // Message header\r
 //  (4) message start\r
@@ -139,7 +138,7 @@ public:
     unsigned int nTime;\r
 \r
     // memory only\r
-    unsigned int nLastFailed;\r
+    unsigned int nLastTry;\r
 \r
     CAddress()\r
     {\r
@@ -183,7 +182,7 @@ public:
         ip = INADDR_NONE;\r
         port = DEFAULT_PORT;\r
         nTime = GetAdjustedTime();\r
-        nLastFailed = 0;\r
+        nLastTry = 0;\r
     }\r
 \r
     bool SetAddress(const char* pszIn)\r
@@ -458,6 +457,7 @@ extern uint64 nLocalHostNonce;
 extern bool fShutdown;\r
 extern array<int, 10> vnThreadsRunning;\r
 extern SOCKET hListenSocket;\r
+extern int64 nThreadSocketHandlerHeartbeat;\r
 \r
 extern vector<CNode*> vNodes;\r
 extern CCriticalSection cs_vNodes;\r
@@ -486,6 +486,10 @@ public:
     CDataStream vRecv;\r
     CCriticalSection cs_vSend;\r
     CCriticalSection cs_vRecv;\r
+    int64 nLastSend;\r
+    int64 nLastRecv;\r
+    int64 nLastSendEmpty;\r
+    int64 nTimeConnected;\r
     unsigned int nPushPos;\r
     CAddress addr;\r
     int nVersion;\r
@@ -523,6 +527,10 @@ public:
         hSocket = hSocketIn;\r
         vSend.SetType(SER_NETWORK);\r
         vRecv.SetType(SER_NETWORK);\r
+        nLastSend = 0;\r
+        nLastRecv = 0;\r
+        nLastSendEmpty = GetTime();\r
+        nTimeConnected = GetTime();\r
         nPushPos = -1;\r
         addr = addrIn;\r
         nVersion = 0;\r
@@ -542,7 +550,7 @@ public:
         CAddress addrYou = (fUseProxy ? CAddress("0.0.0.0") : addr);\r
         CAddress addrMe = (fUseProxy ? CAddress("0.0.0.0") : addrLocalHost);\r
         RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));\r
-        PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe, nLocalHostNonce);\r
+        PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe, nLocalHostNonce, "linux-test5");\r
     }\r
 \r
     ~CNode()\r
@@ -557,11 +565,6 @@ private:
 public:\r
 \r
 \r
-    bool ReadyToDisconnect()\r
-    {\r
-        return fDisconnect || GetRefCount() <= 0;\r
-    }\r
-\r
     int GetRefCount()\r
     {\r
         return max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0);\r
@@ -635,6 +638,8 @@ public:
             AbortMessage();\r
         nPushPos = vSend.size();\r
         vSend << CMessageHeader(pszCommand, 0);\r
+        if (fDebug)\r
+            printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());\r
         printf("sending: %s ", pszCommand);\r
     }\r
 \r
diff --git a/ui.cpp b/ui.cpp
index e12970b..9d7556c 100644 (file)
--- a/ui.cpp
+++ b/ui.cpp
@@ -25,6 +25,7 @@ map<string, string> mapAddressBook;
 bool fRandSendTest = false;\r
 void RandSend();\r
 extern int g_isPainting;\r
+bool fClosedToTray = false;\r
 \r
 // Settings\r
 int fShowGenerated = true;\r
@@ -413,16 +414,17 @@ void Shutdown(void* parg)
 \r
 void CMainFrame::OnClose(wxCloseEvent& event)\r
 {\r
-    if (fMinimizeToTray && fMinimizeOnClose && event.CanVeto() && !IsIconized())\r
+    if (fMinimizeOnClose && event.CanVeto() && !IsIconized())\r
     {\r
         // Divert close to minimize\r
         event.Veto();\r
+        fClosedToTray = true;\r
         Iconize(true);\r
     }\r
     else\r
     {\r
         Destroy();\r
-        _beginthread(Shutdown, 0, NULL);\r
+        CreateThread(Shutdown, NULL);\r
     }\r
 }\r
 \r
@@ -430,7 +432,16 @@ void CMainFrame::OnIconize(wxIconizeEvent& event)
 {\r
     // Hide the task bar button when minimized.\r
     // Event is sent when the frame is minimized or restored.\r
-    Show(!fMinimizeToTray || !event.Iconized());\r
+    if (!event.Iconized())\r
+        fClosedToTray = false;\r
+#ifndef __WXMSW__\r
+    // Tray is not reliable on Linux gnome\r
+    fClosedToTray = false;\r
+#endif\r
+    if (fMinimizeToTray && event.Iconized())\r
+        fClosedToTray = true;\r
+    Show(!fClosedToTray);\r
+    ptaskbaricon->Show(fMinimizeToTray || fClosedToTray);\r
 }\r
 \r
 void CMainFrame::OnMouseEvents(wxMouseEvent& event)\r
@@ -527,7 +538,6 @@ bool CMainFrame::DeleteLine(uint256 hashKey)
 string FormatTxStatus(const CWalletTx& wtx)\r
 {\r
     // Status\r
-    int nDepth = wtx.GetDepthInMainChain();\r
     if (!wtx.IsFinal())\r
     {\r
         if (wtx.nLockTime < 500000000)\r
@@ -535,10 +545,16 @@ string FormatTxStatus(const CWalletTx& wtx)
         else\r
             return strprintf("Open until %s", DateTimeStr(wtx.nLockTime).c_str());\r
     }\r
-    else if (nDepth < 6)\r
-        return strprintf("%d/unconfirmed", nDepth);\r
     else\r
-        return strprintf("%d blocks", nDepth);\r
+    {\r
+        int nDepth = wtx.GetDepthInMainChain();\r
+        if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)\r
+            return strprintf("%d/offline?", nDepth);\r
+        else if (nDepth < 6)\r
+            return strprintf("%d/unconfirmed", nDepth);\r
+        else\r
+            return strprintf("%d blocks", nDepth);\r
+    }\r
 }\r
 \r
 string SingleLine(const string& strIn)\r
@@ -629,9 +645,17 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
                 foreach(const CTxOut& txout, wtx.vout)\r
                     nUnmatured += txout.GetCredit();\r
                 if (wtx.IsInMainChain())\r
-                    strDescription += strprintf(" (%s matures in %d more blocks)", FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());\r
+                {\r
+                    strDescription = strprintf("Generated (%s matures in %d more blocks)", FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());\r
+\r
+                    // Check if the block was requested by anyone\r
+                    if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)\r
+                        strDescription = "Generated - Warning: This block was not received by any other nodes and will probably not be accepted!";\r
+                }\r
                 else\r
-                    strDescription += " (not accepted)";\r
+                {\r
+                    strDescription = "Generated (not accepted)";\r
+                }\r
             }\r
         }\r
         else if (!mapValue["from"].empty() || !mapValue["message"].empty())\r
@@ -701,8 +725,11 @@ bool CMainFrame::InsertTransaction(const CWalletTx& wtx, bool fNew, int nIndex)
                        strStatus,\r
                        nTime ? DateTimeStr(nTime) : "",\r
                        "Payment to yourself",\r
-                       FormatMoney(nNet - nValue, true),\r
-                       FormatMoney(nValue, true));\r
+                       "",\r
+                       "");\r
+            /// issue: can't tell which is the payment and which is the change anymore\r
+            //           FormatMoney(nNet - nValue, true),\r
+            //           FormatMoney(nValue, true));\r
         }\r
         else if (fAllFromMe)\r
         {\r
@@ -1028,6 +1055,9 @@ void CMainFrame::OnPaintListCtrl(wxPaintEvent& event)
     string strStatus = strprintf("     %d connections     %d blocks     %d transactions", vNodes.size(), nBestHeight + 1, nTransactionCount);\r
     m_statusBar->SetStatusText(strStatus, 2);\r
 \r
+    if (fDebug && GetTime() - nThreadSocketHandlerHeartbeat > 60)\r
+        m_statusBar->SetStatusText("     ERROR: ThreadSocketHandler has stopped", 0);\r
+\r
     // Pass through to listctrl to actually do the paint, we're just hooking the message\r
     m_listCtrl->Disconnect(wxEVT_PAINT, (wxObjectEventFunction)NULL, NULL, this);\r
     m_listCtrl->GetEventHandler()->ProcessEvent(event);\r
@@ -1237,7 +1267,19 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
 \r
 \r
 \r
-    strHTML += "<b>Status:</b> " + FormatTxStatus(wtx) + "<br>";\r
+    strHTML += "<b>Status:</b> " + FormatTxStatus(wtx);\r
+    int nRequests = wtx.GetRequestCount();\r
+    if (nRequests != -1)\r
+    {\r
+        if (nRequests == 0)\r
+            strHTML += ", has not been successfully broadcast yet";\r
+        else if (nRequests == 1)\r
+            strHTML += strprintf(", broadcast through %d node", nRequests);\r
+        else\r
+            strHTML += strprintf(", broadcast through %d nodes", nRequests);\r
+    }\r
+    strHTML += "<br>";\r
+\r
     strHTML += "<b>Date:</b> " + (nTime ? DateTimeStr(nTime) : "") + "<br>";\r
 \r
 \r
@@ -1366,9 +1408,10 @@ CTxDetailsDialog::CTxDetailsDialog(wxWindow* parent, CWalletTx wtx) : CTxDetails
             if (fAllToMe)\r
             {\r
                 // Payment to self\r
-                int64 nValue = wtx.vout[0].nValue;\r
-                strHTML += "<b>Debit:</b> " + FormatMoney(-nValue) + "<br>";\r
-                strHTML += "<b>Credit:</b> " + FormatMoney(nValue) + "<br>";\r
+                /// issue: can't tell which is the payment and which is the change anymore\r
+                //int64 nValue = wtx.vout[0].nValue;\r
+                //strHTML += "<b>Debit:</b> " + FormatMoney(-nValue) + "<br>";\r
+                //strHTML += "<b>Credit:</b> " + FormatMoney(nValue) + "<br>";\r
             }\r
 \r
             int64 nTxFee = nDebit - wtx.GetValueOut();\r
@@ -1469,6 +1512,9 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent)
     //m_listBox->Append("Test 2");\r
     m_listBox->SetSelection(0);\r
     SelectPage(0);\r
+#ifndef __WXMSW__\r
+    m_checkBoxMinimizeOnClose->SetLabel("&Minimize on close");\r
+#endif\r
 \r
     // Init values\r
     m_textCtrlTransactionFee->SetValue(FormatMoney(nTransactionFee));\r
@@ -1481,9 +1527,7 @@ COptionsDialog::COptionsDialog(wxWindow* parent) : COptionsDialogBase(parent)
     m_spinCtrlLimitProcessors->SetRange(1, nProcessors);\r
     m_checkBoxStartOnSystemStartup->SetValue(fTmpStartOnSystemStartup = GetStartOnSystemStartup());\r
     m_checkBoxMinimizeToTray->SetValue(fMinimizeToTray);\r
-    m_checkBoxMinimizeOnClose->Enable(fMinimizeToTray);\r
-    m_checkBoxMinimizeOnClose->SetValue(fMinimizeToTray && fMinimizeOnClose);\r
-    fTmpMinimizeOnClose = fMinimizeOnClose;\r
+    m_checkBoxMinimizeOnClose->SetValue(fMinimizeOnClose);\r
     m_checkBoxUseProxy->SetValue(fUseProxy);\r
     m_textCtrlProxyIP->Enable(fUseProxy);\r
     m_textCtrlProxyPort->Enable(fUseProxy);\r
@@ -1521,22 +1565,6 @@ void COptionsDialog::OnCheckBoxLimitProcessors(wxCommandEvent& event)
     m_spinCtrlLimitProcessors->Enable(event.IsChecked());\r
 }\r
 \r
-void COptionsDialog::OnCheckBoxMinimizeToTray(wxCommandEvent& event)\r
-{\r
-    m_checkBoxMinimizeOnClose->Enable(event.IsChecked());\r
-\r
-    // Save the value in fTmpMinimizeOnClose so we can\r
-    // show the checkbox unchecked when its parent is unchecked\r
-    if (event.IsChecked())\r
-        m_checkBoxMinimizeOnClose->SetValue(fTmpMinimizeOnClose);\r
-    else\r
-    {\r
-        fTmpMinimizeOnClose = m_checkBoxMinimizeOnClose->GetValue();\r
-        m_checkBoxMinimizeOnClose->SetValue(false);\r
-    }\r
-\r
-}\r
-\r
 void COptionsDialog::OnCheckBoxUseProxy(wxCommandEvent& event)\r
 {\r
     m_textCtrlProxyIP->Enable(event.IsChecked());\r
@@ -1608,12 +1636,12 @@ void COptionsDialog::OnButtonApply(wxCommandEvent& event)
     {\r
         fMinimizeToTray = m_checkBoxMinimizeToTray->GetValue();\r
         walletdb.WriteSetting("fMinimizeToTray", fMinimizeToTray);\r
-        ptaskbaricon->Show(fMinimizeToTray);\r
+        ptaskbaricon->Show(fMinimizeToTray || fClosedToTray);\r
     }\r
 \r
-    if (fMinimizeOnClose != (fMinimizeToTray ? m_checkBoxMinimizeOnClose->GetValue() : fTmpMinimizeOnClose))\r
+    if (fMinimizeOnClose != m_checkBoxMinimizeOnClose->GetValue())\r
     {\r
-        fMinimizeOnClose = (fMinimizeToTray ? m_checkBoxMinimizeOnClose->GetValue() : fTmpMinimizeOnClose);\r
+        fMinimizeOnClose = m_checkBoxMinimizeOnClose->GetValue();\r
         walletdb.WriteSetting("fMinimizeOnClose", fMinimizeOnClose);\r
     }\r
 \r
@@ -1643,6 +1671,9 @@ CAboutDialog::CAboutDialog(wxWindow* parent) : CAboutDialogBase(parent)
     if (str.Find('Â') != wxNOT_FOUND)\r
         str.Remove(str.Find('Â'), 1);\r
     m_staticTextMain->SetLabel(str);\r
+#ifndef __WXMSW__\r
+    SetSize(510, 380);\r
+#endif\r
 }\r
 \r
 void CAboutDialog::OnButtonOK(wxCommandEvent& event)\r
@@ -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()));\r
     m_textCtrlStatus->SetValue("");\r
 \r
-    _beginthread(SendingDialogStartTransfer, 0, this);\r
+    CreateThread(SendingDialogStartTransfer, this);\r
 }\r
 \r
 CSendingDialog::~CSendingDialog()\r
@@ -2856,7 +2887,7 @@ CViewProductDialog::CViewProductDialog(wxWindow* parent, const CProduct& product
     this->Layout();\r
 \r
     // Request details from seller\r
-    _beginthread(ThreadRequestProductDetails, 0, new pair<CProduct, wxEvtHandler*>(product, GetEventHandler()));\r
+    CreateThread(ThreadRequestProductDetails, new pair<CProduct, wxEvtHandler*>(product, GetEventHandler()));\r
 }\r
 \r
 CViewProductDialog::~CViewProductDialog()\r
@@ -3256,6 +3287,7 @@ void CEditReviewDialog::GetReview(CReview& review)
 enum\r
 {\r
     ID_TASKBAR_RESTORE = 10001,\r
+    ID_TASKBAR_OPTIONS,\r
     ID_TASKBAR_GENERATE,\r
     ID_TASKBAR_EXIT,\r
 };\r
@@ -3263,6 +3295,7 @@ enum
 BEGIN_EVENT_TABLE(CMyTaskBarIcon, wxTaskBarIcon)\r
     EVT_TASKBAR_LEFT_DCLICK(CMyTaskBarIcon::OnLeftButtonDClick)\r
     EVT_MENU(ID_TASKBAR_RESTORE, CMyTaskBarIcon::OnMenuRestore)\r
+    EVT_MENU(ID_TASKBAR_OPTIONS, CMyTaskBarIcon::OnMenuOptions)\r
     EVT_MENU(ID_TASKBAR_GENERATE, CMyTaskBarIcon::OnMenuGenerate)\r
     EVT_UPDATE_UI(ID_TASKBAR_GENERATE, CMyTaskBarIcon::OnUpdateUIGenerate)\r
     EVT_MENU(ID_TASKBAR_EXIT, CMyTaskBarIcon::OnMenuExit)\r
@@ -3312,9 +3345,18 @@ void CMyTaskBarIcon::OnMenuRestore(wxCommandEvent& event)
     Restore();\r
 }\r
 \r
+void CMyTaskBarIcon::OnMenuOptions(wxCommandEvent& event)\r
+{\r
+    // Since it's modal, get the main window to do it\r
+    wxCommandEvent event2(wxEVT_COMMAND_MENU_SELECTED, wxID_MENUOPTIONSOPTIONS);\r
+    pframeMain->AddPendingEvent(event2);\r
+}\r
+\r
 void CMyTaskBarIcon::Restore()\r
 {\r
     pframeMain->Show();\r
+    wxIconizeEvent event(0, false);\r
+    pframeMain->AddPendingEvent(event);\r
     pframeMain->Iconize(false);\r
     pframeMain->Raise();\r
 }\r
@@ -3344,6 +3386,7 @@ wxMenu* CMyTaskBarIcon::CreatePopupMenu()
 {\r
     wxMenu* pmenu = new wxMenu;\r
     pmenu->Append(ID_TASKBAR_RESTORE, "&Open Bitcoin");\r
+    pmenu->Append(ID_TASKBAR_OPTIONS, "O&ptions...");\r
     pmenu->AppendCheckItem(ID_TASKBAR_GENERATE, "&Generate Coins")->Check(fGenerateBitcoins);\r
 #ifndef __WXMAC_OSX__ // Mac has built-in quit menu\r
     pmenu->AppendSeparator();\r
@@ -3582,7 +3625,7 @@ bool CMyApp::OnInit2()
             {\r
                 CBlockIndex* pindex = (*mi).second;\r
                 CBlock block;\r
-                block.ReadFromDisk(pindex, true);\r
+                block.ReadFromDisk(pindex);\r
                 block.BuildMerkleTree();\r
                 block.print();\r
                 printf("\n");\r
@@ -3632,20 +3675,20 @@ bool CMyApp::OnInit2()
     if (mapArgs.count("-min"))\r
         pframeMain->Iconize(true);\r
     pframeMain->Show(true);  // have to show first to get taskbar button to hide\r
-    pframeMain->Show(!fMinimizeToTray || !pframeMain->IsIconized());\r
-    ptaskbaricon->Show(fMinimizeToTray);\r
+    if (fMinimizeToTray && pframeMain->IsIconized())\r
+        fClosedToTray = true;\r
+    pframeMain->Show(!fClosedToTray);\r
+    ptaskbaricon->Show(fMinimizeToTray || fClosedToTray);\r
 \r
-    _beginthread(ThreadDelayedRepaint, 0, NULL);\r
+    CreateThread(ThreadDelayedRepaint, NULL);\r
 \r
     if (!CheckDiskSpace())\r
         return false;\r
 \r
     RandAddSeedPerfmon();\r
 \r
-    if (!StartNode(strErrors))\r
-        wxMessageBox(strErrors, "Bitcoin");\r
-\r
-    GenerateBitcoins(fGenerateBitcoins);\r
+    if (!CreateThread(StartNode, NULL))\r
+        wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin");\r
 \r
     if (fFirstRun)\r
         SetStartOnSystemStartup(true);\r
diff --git a/ui.h b/ui.h
index a919c36..c4bf8b6 100644 (file)
--- a/ui.h
+++ b/ui.h
@@ -112,7 +112,6 @@ protected:
     void OnListBox(wxCommandEvent& event);\r
     void OnKillFocusTransactionFee(wxFocusEvent& event);\r
     void OnCheckBoxLimitProcessors(wxCommandEvent& event);\r
-    void OnCheckBoxMinimizeToTray(wxCommandEvent& event);\r
     void OnCheckBoxUseProxy(wxCommandEvent& event);\r
     void OnKillFocusProxy(wxFocusEvent& event);\r
 \r
@@ -447,6 +446,7 @@ protected:
     // Event handlers\r
     void OnLeftButtonDClick(wxTaskBarIconEvent& event);\r
     void OnMenuRestore(wxCommandEvent& event);\r
+    void OnMenuOptions(wxCommandEvent& event);\r
     void OnUpdateUIGenerate(wxUpdateUIEvent& event);\r
     void OnMenuGenerate(wxCommandEvent& event);\r
     void OnMenuExit(wxCommandEvent& event);\r
index 7bc8081..f05f109 100644 (file)
@@ -45,7 +45,7 @@ CMainFrameBase::CMainFrameBase( wxWindow* parent, wxWindowID id, const wxString&
        m_menuOptions->Append( m_menuOptionsChangeYourAddress );\r
        \r
        wxMenuItem* m_menuOptionsOptions;\r
-       m_menuOptionsOptions = new wxMenuItem( m_menuOptions, wxID_ANY, wxString( wxT("&Options...") ) , wxEmptyString, wxITEM_NORMAL );\r
+       m_menuOptionsOptions = new wxMenuItem( m_menuOptions, wxID_MENUOPTIONSOPTIONS, wxString( wxT("&Options...") ) , wxEmptyString, wxITEM_NORMAL );\r
        m_menuOptions->Append( m_menuOptionsOptions );\r
        \r
        m_menubar->Append( m_menuOptions, wxT("&Options") );\r
@@ -428,21 +428,13 @@ COptionsDialogBase::COptionsDialogBase( wxWindow* parent, wxWindowID id, const w
        \r
        bSizer69->Add( m_checkBoxStartOnSystemStartup, 0, wxALL, 5 );\r
        \r
-       m_checkBoxMinimizeToTray = new wxCheckBox( m_panelMain, wxID_ANY, wxT("&Minimize to the system tray instead of the taskbar"), wxDefaultPosition, wxDefaultSize, 0 );\r
+       m_checkBoxMinimizeToTray = new wxCheckBox( m_panelMain, wxID_ANY, wxT("&Minimize to the tray instead of the taskbar"), wxDefaultPosition, wxDefaultSize, 0 );\r
        \r
        bSizer69->Add( m_checkBoxMinimizeToTray, 0, wxALL, 5 );\r
        \r
-       wxBoxSizer* bSizer101;\r
-       bSizer101 = new wxBoxSizer( wxHORIZONTAL );\r
+       m_checkBoxMinimizeOnClose = new wxCheckBox( m_panelMain, wxID_ANY, wxT("M&inimize to the tray on close"), wxDefaultPosition, wxDefaultSize, 0 );\r
        \r
-       \r
-       bSizer101->Add( 16, 0, 0, 0, 5 );\r
-       \r
-       m_checkBoxMinimizeOnClose = new wxCheckBox( m_panelMain, wxID_ANY, wxT("Mi&nimize to system tray on close"), wxDefaultPosition, wxDefaultSize, 0 );\r
-       \r
-       bSizer101->Add( m_checkBoxMinimizeOnClose, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );\r
-       \r
-       bSizer69->Add( bSizer101, 1, wxEXPAND, 5 );\r
+       bSizer69->Add( m_checkBoxMinimizeOnClose, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );\r
        \r
        wxBoxSizer* bSizer102;\r
        bSizer102 = new wxBoxSizer( wxHORIZONTAL );\r
index 2cb99e9..e0c1521 100644 (file)
--- a/uibase.h
+++ b/uibase.h
 #define wxID_MAINFRAME 1000\r
 #define wxID_VIEWSHOWGENERATED 1001\r
 #define wxID_OPTIONSGENERATEBITCOINS 1002\r
-#define wxID_BUTTONSEND 1003\r
-#define wxID_BUTTONRECEIVE 1004\r
-#define wxID_TEXTCTRLADDRESS 1005\r
-#define wxID_BUTTONCOPY 1006\r
-#define wxID_BUTTONCHANGE 1007\r
-#define wxID_TRANSACTIONFEE 1008\r
-#define wxID_PROXYIP 1009\r
-#define wxID_PROXYPORT 1010\r
-#define wxID_TEXTCTRLPAYTO 1011\r
-#define wxID_BUTTONPASTE 1012\r
-#define wxID_BUTTONADDRESSBOOK 1013\r
-#define wxID_TEXTCTRLAMOUNT 1014\r
-#define wxID_CHOICETRANSFERTYPE 1015\r
-#define wxID_LISTCTRL 1016\r
-#define wxID_BUTTONRENAME 1017\r
-#define wxID_BUTTONNEW 1018\r
-#define wxID_BUTTONEDIT 1019\r
-#define wxID_BUTTONDELETE 1020\r
-#define wxID_DEL0 1021\r
-#define wxID_DEL1 1022\r
-#define wxID_DEL2 1023\r
-#define wxID_DEL3 1024\r
-#define wxID_DEL4 1025\r
-#define wxID_DEL5 1026\r
-#define wxID_DEL6 1027\r
-#define wxID_DEL7 1028\r
-#define wxID_DEL8 1029\r
-#define wxID_DEL9 1030\r
-#define wxID_DEL10 1031\r
-#define wxID_DEL11 1032\r
-#define wxID_DEL12 1033\r
-#define wxID_DEL13 1034\r
-#define wxID_DEL14 1035\r
-#define wxID_DEL15 1036\r
-#define wxID_DEL16 1037\r
-#define wxID_DEL17 1038\r
-#define wxID_DEL18 1039\r
-#define wxID_DEL19 1040\r
-#define wxID_BUTTONPREVIEW 1041\r
-#define wxID_BUTTONSAMPLE 1042\r
-#define wxID_CANCEL2 1043\r
-#define wxID_BUTTONBACK 1044\r
-#define wxID_BUTTONNEXT 1045\r
-#define wxID_SUBMIT 1046\r
-#define wxID_TEXTCTRL 1047\r
+#define wxID_MENUOPTIONSOPTIONS 1003\r
+#define wxID_BUTTONSEND 1004\r
+#define wxID_BUTTONRECEIVE 1005\r
+#define wxID_TEXTCTRLADDRESS 1006\r
+#define wxID_BUTTONCOPY 1007\r
+#define wxID_BUTTONCHANGE 1008\r
+#define wxID_TRANSACTIONFEE 1009\r
+#define wxID_PROXYIP 1010\r
+#define wxID_PROXYPORT 1011\r
+#define wxID_TEXTCTRLPAYTO 1012\r
+#define wxID_BUTTONPASTE 1013\r
+#define wxID_BUTTONADDRESSBOOK 1014\r
+#define wxID_TEXTCTRLAMOUNT 1015\r
+#define wxID_CHOICETRANSFERTYPE 1016\r
+#define wxID_LISTCTRL 1017\r
+#define wxID_BUTTONRENAME 1018\r
+#define wxID_BUTTONNEW 1019\r
+#define wxID_BUTTONEDIT 1020\r
+#define wxID_BUTTONDELETE 1021\r
+#define wxID_DEL0 1022\r
+#define wxID_DEL1 1023\r
+#define wxID_DEL2 1024\r
+#define wxID_DEL3 1025\r
+#define wxID_DEL4 1026\r
+#define wxID_DEL5 1027\r
+#define wxID_DEL6 1028\r
+#define wxID_DEL7 1029\r
+#define wxID_DEL8 1030\r
+#define wxID_DEL9 1031\r
+#define wxID_DEL10 1032\r
+#define wxID_DEL11 1033\r
+#define wxID_DEL12 1034\r
+#define wxID_DEL13 1035\r
+#define wxID_DEL14 1036\r
+#define wxID_DEL15 1037\r
+#define wxID_DEL16 1038\r
+#define wxID_DEL17 1039\r
+#define wxID_DEL18 1040\r
+#define wxID_DEL19 1041\r
+#define wxID_BUTTONPREVIEW 1042\r
+#define wxID_BUTTONSAMPLE 1043\r
+#define wxID_CANCEL2 1044\r
+#define wxID_BUTTONBACK 1045\r
+#define wxID_BUTTONNEXT 1046\r
+#define wxID_SUBMIT 1047\r
+#define wxID_TEXTCTRL 1048\r
 \r
 ///////////////////////////////////////////////////////////////////////////////\r
 /// Class CMainFrameBase\r
@@ -203,7 +204,6 @@ class COptionsDialogBase : public wxDialog
                wxStaticText* m_staticText35;\r
                wxCheckBox* m_checkBoxStartOnSystemStartup;\r
                wxCheckBox* m_checkBoxMinimizeToTray;\r
-               \r
                wxCheckBox* m_checkBoxMinimizeOnClose;\r
                wxCheckBox* m_checkBoxUseProxy;\r
                \r
index 3aa1c86..58a99bd 100644 (file)
@@ -70,7 +70,7 @@
             <event name="OnSetFocus"></event>\r
             <event name="OnSize"></event>\r
             <event name="OnUpdateUI"></event>\r
-            <object class="wxMenuBar" expanded="0">\r
+            <object class="wxMenuBar" expanded="1">\r
                 <property name="bg">240,240,240</property>\r
                 <property name="context_help"></property>\r
                 <property name="enabled">1</property>\r
                         <property name="checked">0</property>\r
                         <property name="enabled">1</property>\r
                         <property name="help"></property>\r
-                        <property name="id">wxID_ANY</property>\r
+                        <property name="id">wxID_MENUOPTIONSOPTIONS</property>\r
                         <property name="kind">wxITEM_NORMAL</property>\r
                         <property name="label">&amp;Options...</property>\r
                         <property name="name">m_menuOptionsOptions</property>\r
                                                         <property name="font"></property>\r
                                                         <property name="hidden">0</property>\r
                                                         <property name="id">wxID_ANY</property>\r
-                                                        <property name="label">&amp;Minimize to the system tray instead of the taskbar</property>\r
+                                                        <property name="label">&amp;Minimize to the tray instead of the taskbar</property>\r
                                                         <property name="maximum_size"></property>\r
                                                         <property name="minimum_size"></property>\r
                                                         <property name="name">m_checkBoxMinimizeToTray</property>\r
                                                 </object>\r
                                                 <object class="sizeritem" expanded="1">\r
                                                     <property name="border">5</property>\r
-                                                    <property name="flag">wxEXPAND</property>\r
-                                                    <property name="proportion">1</property>\r
-                                                    <object class="wxBoxSizer" expanded="1">\r
+                                                    <property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>\r
+                                                    <property name="proportion">0</property>\r
+                                                    <object class="wxCheckBox" expanded="1">\r
+                                                        <property name="bg"></property>\r
+                                                        <property name="checked">0</property>\r
+                                                        <property name="context_help"></property>\r
+                                                        <property name="enabled">1</property>\r
+                                                        <property name="fg"></property>\r
+                                                        <property name="font"></property>\r
+                                                        <property name="hidden">0</property>\r
+                                                        <property name="id">wxID_ANY</property>\r
+                                                        <property name="label">M&amp;inimize to the tray on close</property>\r
+                                                        <property name="maximum_size"></property>\r
                                                         <property name="minimum_size"></property>\r
-                                                        <property name="name">bSizer101</property>\r
-                                                        <property name="orient">wxHORIZONTAL</property>\r
-                                                        <property name="permission">none</property>\r
-                                                        <object class="sizeritem" expanded="1">\r
-                                                            <property name="border">5</property>\r
-                                                            <property name="flag"></property>\r
-                                                            <property name="proportion">0</property>\r
-                                                            <object class="spacer" expanded="1">\r
-                                                                <property name="height">0</property>\r
-                                                                <property name="permission">protected</property>\r
-                                                                <property name="width">16</property>\r
-                                                            </object>\r
-                                                        </object>\r
-                                                        <object class="sizeritem" expanded="1">\r
-                                                            <property name="border">5</property>\r
-                                                            <property name="flag">wxALL|wxALIGN_CENTER_VERTICAL</property>\r
-                                                            <property name="proportion">0</property>\r
-                                                            <object class="wxCheckBox" expanded="1">\r
-                                                                <property name="bg"></property>\r
-                                                                <property name="checked">0</property>\r
-                                                                <property name="context_help"></property>\r
-                                                                <property name="enabled">1</property>\r
-                                                                <property name="fg"></property>\r
-                                                                <property name="font"></property>\r
-                                                                <property name="hidden">0</property>\r
-                                                                <property name="id">wxID_ANY</property>\r
-                                                                <property name="label">Mi&amp;nimize to system tray on close</property>\r
-                                                                <property name="maximum_size"></property>\r
-                                                                <property name="minimum_size"></property>\r
-                                                                <property name="name">m_checkBoxMinimizeOnClose</property>\r
-                                                                <property name="permission">protected</property>\r
-                                                                <property name="pos"></property>\r
-                                                                <property name="size"></property>\r
-                                                                <property name="style"></property>\r
-                                                                <property name="subclass"></property>\r
-                                                                <property name="tooltip"></property>\r
-                                                                <property name="window_extra_style"></property>\r
-                                                                <property name="window_name"></property>\r
-                                                                <property name="window_style"></property>\r
-                                                                <event name="OnChar"></event>\r
-                                                                <event name="OnCheckBox"></event>\r
-                                                                <event name="OnEnterWindow"></event>\r
-                                                                <event name="OnEraseBackground"></event>\r
-                                                                <event name="OnKeyDown"></event>\r
-                                                                <event name="OnKeyUp"></event>\r
-                                                                <event name="OnKillFocus"></event>\r
-                                                                <event name="OnLeaveWindow"></event>\r
-                                                                <event name="OnLeftDClick"></event>\r
-                                                                <event name="OnLeftDown"></event>\r
-                                                                <event name="OnLeftUp"></event>\r
-                                                                <event name="OnMiddleDClick"></event>\r
-                                                                <event name="OnMiddleDown"></event>\r
-                                                                <event name="OnMiddleUp"></event>\r
-                                                                <event name="OnMotion"></event>\r
-                                                                <event name="OnMouseEvents"></event>\r
-                                                                <event name="OnMouseWheel"></event>\r
-                                                                <event name="OnPaint"></event>\r
-                                                                <event name="OnRightDClick"></event>\r
-                                                                <event name="OnRightDown"></event>\r
-                                                                <event name="OnRightUp"></event>\r
-                                                                <event name="OnSetFocus"></event>\r
-                                                                <event name="OnSize"></event>\r
-                                                                <event name="OnUpdateUI"></event>\r
-                                                            </object>\r
-                                                        </object>\r
+                                                        <property name="name">m_checkBoxMinimizeOnClose</property>\r
+                                                        <property name="permission">protected</property>\r
+                                                        <property name="pos"></property>\r
+                                                        <property name="size"></property>\r
+                                                        <property name="style"></property>\r
+                                                        <property name="subclass"></property>\r
+                                                        <property name="tooltip"></property>\r
+                                                        <property name="window_extra_style"></property>\r
+                                                        <property name="window_name"></property>\r
+                                                        <property name="window_style"></property>\r
+                                                        <event name="OnChar"></event>\r
+                                                        <event name="OnCheckBox"></event>\r
+                                                        <event name="OnEnterWindow"></event>\r
+                                                        <event name="OnEraseBackground"></event>\r
+                                                        <event name="OnKeyDown"></event>\r
+                                                        <event name="OnKeyUp"></event>\r
+                                                        <event name="OnKillFocus"></event>\r
+                                                        <event name="OnLeaveWindow"></event>\r
+                                                        <event name="OnLeftDClick"></event>\r
+                                                        <event name="OnLeftDown"></event>\r
+                                                        <event name="OnLeftUp"></event>\r
+                                                        <event name="OnMiddleDClick"></event>\r
+                                                        <event name="OnMiddleDown"></event>\r
+                                                        <event name="OnMiddleUp"></event>\r
+                                                        <event name="OnMotion"></event>\r
+                                                        <event name="OnMouseEvents"></event>\r
+                                                        <event name="OnMouseWheel"></event>\r
+                                                        <event name="OnPaint"></event>\r
+                                                        <event name="OnRightDClick"></event>\r
+                                                        <event name="OnRightDown"></event>\r
+                                                        <event name="OnRightUp"></event>\r
+                                                        <event name="OnSetFocus"></event>\r
+                                                        <event name="OnSize"></event>\r
+                                                        <event name="OnUpdateUI"></event>\r
                                                     </object>\r
                                                 </object>\r
                                                 <object class="sizeritem" expanded="1">\r
index 4a5b983..7a94773 100644 (file)
--- a/util.cpp
+++ b/util.cpp
@@ -85,14 +85,14 @@ void RandAddSeed()
 \r
 void RandAddSeedPerfmon()\r
 {\r
-#ifdef __WXMSW__\r
-    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom\r
     // This can take up to 2 seconds, so only do it every 10 minutes\r
     static int64 nLastPerfmon;\r
     if (GetTime() < nLastPerfmon + 10 * 60)\r
         return;\r
     nLastPerfmon = GetTime();\r
 \r
+#ifdef __WXMSW__\r
+    // Don't need this on Linux, OpenSSL automatically uses /dev/urandom\r
     // Seed with the entire set of perfmon data\r
     unsigned char pdata[250000];\r
     memset(pdata, 0, sizeof(pdata));\r
@@ -109,9 +109,30 @@ void RandAddSeedPerfmon()
 \r
         printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str(), nSize);\r
     }\r
+#else\r
+    printf("%s RandAddSeed()\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());\r
 #endif\r
 }\r
 \r
+uint64 GetRand(uint64 nMax)\r
+{\r
+    if (nMax == 0)\r
+        return 0;\r
+\r
+    // The range of the random source must be a multiple of the modulus\r
+    // to give every possible output value an equal possibility\r
+    uint64 nRange = (UINT64_MAX / nMax) * nMax;\r
+    uint64 nRand = 0;\r
+    do\r
+        RAND_bytes((unsigned char*)&nRand, sizeof(nRand));\r
+    while (nRand >= nRange);\r
+    return (nRand % nMax);\r
+}\r
+\r
+\r
+\r
+\r
+\r
 \r
 \r
 \r
@@ -449,28 +470,6 @@ string GetDataDir()
 \r
 \r
 \r
-uint64 GetRand(uint64 nMax)\r
-{\r
-    if (nMax == 0)\r
-        return 0;\r
-\r
-    // The range of the random source must be a multiple of the modulus\r
-    // to give every possible output value an equal possibility\r
-    uint64 nRange = (_UI64_MAX / nMax) * nMax;\r
-    uint64 nRand = 0;\r
-    do\r
-        RAND_bytes((unsigned char*)&nRand, sizeof(nRand));\r
-    while (nRand >= nRange);\r
-    return (nRand % nMax);\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
 \r
 \r
 //\r
@@ -483,7 +482,6 @@ uint64 GetRand(uint64 nMax)
 // note: NTP isn't implemented yet, so until then we just use the median\r
 //  of other nodes clocks to correct ours.\r
 //\r
-\r
 int64 GetTime()\r
 {\r
     return time(NULL);\r
diff --git a/util.h b/util.h
index 8fcfcd0..ddac449 100644 (file)
--- a/util.h
+++ b/util.h
@@ -54,9 +54,13 @@ inline T& REF(const T& val)
     return (T&)val;\r
 }\r
 \r
-#ifndef __WXMSW__\r
-#define _UI64_MAX           UINT64_MAX\r
-#define _I64_MAX            INT64_MAX\r
+#ifdef __WXMSW__\r
+#define MSG_NOSIGNAL        0\r
+#define MSG_DONTWAIT        0\r
+#define UINT64_MAX          _UI64_MAX\r
+#define INT64_MAX           _I64_MAX\r
+#define INT64_MIN           _I64_MIN\r
+#else\r
 #define WSAGetLastError()   errno\r
 #define WSAEWOULDBLOCK      EWOULDBLOCK\r
 #define WSAEMSGSIZE         EMSGSIZE\r
@@ -74,18 +78,6 @@ typedef u_int SOCKET;
 #define MAX_PATH            1024\r
 #define Sleep(n)            wxMilliSleep(n)\r
 #define Beep(n1,n2)         (0)\r
-inline int _beginthread(void(*pfn)(void*), unsigned nStack, void* parg) { thread(bind(pfn, parg)); return 0; }\r
-inline void _endthread() { pthread_exit(NULL); }\r
-inline int GetCurrentThread() { return 0; }\r
-// threads are processes on linux, so setpriority affects just the one thread\r
-inline void SetThreadPriority(int nThread, int nPriority) { setpriority(PRIO_PROCESS, getpid(), nPriority); }\r
-#define THREAD_PRIORITY_LOWEST          PRIO_MIN\r
-#define THREAD_PRIORITY_BELOW_NORMAL    2\r
-#define THREAD_PRIORITY_NORMAL          0\r
-#define THREAD_PRIORITY_ABOVE_NORMAL    0\r
-#endif\r
-#ifndef MSG_NOSIGNAL\r
-#define MSG_NOSIGNAL        0\r
 #endif\r
 \r
 \r
@@ -133,6 +125,7 @@ void AddTimeData(unsigned int ip, int64 nTime);
 \r
 \r
 \r
+\r
 // Wrapper to automatically initialize critical sections\r
 class CCriticalSection\r
 {\r
@@ -201,8 +194,6 @@ public:
 \r
 \r
 \r
-\r
-\r
 inline int OutputDebugStringF(const char* pszFormat, ...)\r
 {\r
     int ret = 0;\r
@@ -498,3 +489,83 @@ inline uint160 Hash160(const vector<unsigned char>& vch)
     RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);\r
     return hash2;\r
 }\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+// Note: It turns out we might have been able to use boost::thread\r
+// by using TerminateThread(boost::thread.native_handle(), 0);\r
+#ifdef __WXMSW__\r
+typedef HANDLE pthread_t;\r
+\r
+inline pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=false)\r
+{\r
+    DWORD nUnused = 0;\r
+    HANDLE hthread =\r
+        CreateThread(\r
+            NULL,                        // default security\r
+            0,                           // inherit stack size from parent\r
+            (LPTHREAD_START_ROUTINE)pfn, // function pointer\r
+            parg,                        // argument\r
+            0,                           // creation option, start immediately\r
+            &nUnused);                   // thread identifier\r
+    if (hthread == NULL)\r
+    {\r
+        printf("Error: CreateThread() returned %d\n", GetLastError());\r
+        return (pthread_t)0;\r
+    }\r
+    if (!fWantHandle)\r
+    {\r
+        CloseHandle(hthread);\r
+        return (pthread_t)-1;\r
+    }\r
+    return hthread;\r
+}\r
+\r
+inline void SetThreadPriority(int nPriority)\r
+{\r
+    SetThreadPriority(GetCurrentThread(), nPriority);\r
+}\r
+#else\r
+inline pthread_t CreateThread(void(*pfn)(void*), void* parg, bool fWantHandle=false)\r
+{\r
+    pthread_t hthread = 0;\r
+    int ret = pthread_create(&hthread, NULL, (void*(*)(void*))pfn, parg);\r
+    if (ret != 0)\r
+    {\r
+        printf("Error: pthread_create() returned %d\n", ret);\r
+        return (pthread_t)0;\r
+    }\r
+    if (!fWantHandle)\r
+        return (pthread_t)-1;\r
+    return hthread;\r
+}\r
+\r
+#define THREAD_PRIORITY_LOWEST          PRIO_MIN\r
+#define THREAD_PRIORITY_BELOW_NORMAL    2\r
+#define THREAD_PRIORITY_NORMAL          0\r
+#define THREAD_PRIORITY_ABOVE_NORMAL    0\r
+\r
+inline void SetThreadPriority(int nPriority)\r
+{\r
+    // threads are processes on linux, so PRIO_PROCESS affects just the one thread\r
+    setpriority(PRIO_PROCESS, getpid(), nPriority);\r
+}\r
+\r
+inline bool TerminateThread(pthread_t hthread, unsigned int nExitCode)\r
+{\r
+    return (pthread_cancel(hthread) == 0);\r
+}\r
+\r
+inline void ExitThread(unsigned int nExitCode)\r
+{\r
+    pthread_exit((void*)nExitCode);\r
+}\r
+#endif\r