<NME> netbase.h
<BEF> // Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_NETBASE_H
#define BITCOIN_NETBASE_H

#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif

#include "compat.h"
#include "netaddress.h"
#include "serialize.h"

#include <stdint.h>
#include <string>
#include <vector>

extern int nConnectTimeout;
extern bool fNameLookup;

//! -timeout default
static const int DEFAULT_CONNECT_TIMEOUT = 5000;
//! -dns default
static const int DEFAULT_NAME_LOOKUP = true;

class proxyType
{
public:
    proxyType(): randomize_credentials(false) {}
    proxyType(const CService &_proxy, bool _randomize_credentials=false): proxy(_proxy), randomize_credentials(_randomize_credentials) {}

    bool IsValid() const { return proxy.IsValid(); }

    CService proxy;
    bool randomize_credentials;
};

enum Network ParseNetwork(std::string net);
std::string GetNetworkName(enum Network net);
void SplitHostPort(std::string in, int &portOut, std::string &hostOut);
bool SetProxy(enum Network net, const proxyType &addrProxy);
bool GetProxy(enum Network net, proxyType &proxyInfoOut);
bool IsProxy(const CNetAddr &addr);
bool SetNameProxy(const proxyType &addrProxy);
bool HaveNameProxy();
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup);
bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup);
bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup);
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions);
CService LookupNumeric(const char *pszName, int portDefault = 0);
bool LookupSubNet(const char *pszName, CSubNet& subnet);
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0);
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0);
/** Return readable error string for a network error code */
std::string NetworkErrorString(int err);
/** Close socket and set hSocket to INVALID_SOCKET */
bool CloseSocket(SOCKET& hSocket);
/** Disable or enable blocking-mode for a socket */
bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking);
/**
 * Convert milliseconds to a struct timeval for e.g. select.
 */
struct timeval MillisToTimeval(int64_t nTimeout);
void InterruptSocks5(bool interrupt);

#endif // BITCOIN_NETBASE_H
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0, bool fAllowLookup = true);
bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0);
bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);
bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout);


<MSG> Merge branch 'keepnode' of https://github.com/TheBlueMatt/bitcoin

<DFF> @@ -128,6 +128,7 @@ class CService : public CNetAddr
 bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0, bool fAllowLookup = true);
 bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0);
 bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);
+bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault = 0, bool fAllowLookup = true, int nMaxSolutions = 0);
 bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
 bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout);
 

{'commit': 'diff --git a/src/init.cpp b/src/init.cpp\nindex e01516eb3..890a7d03a 100644\n--- a/src/init.cpp\n+++ b/src/init.cpp\n@@ -192,7 +192,7 @@ bool AppInit2(int argc, char* argv[])\n             "  -dns             \\t  "   + _("Allow DNS lookups for addnode and connect") + "\\n" +\n             "  -port=<port>     \\t\\t  " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\\n" +\n             "  -maxconnections=<n>\\t  " + _("Maintain at most <n> connections to peers (default: 125)") + "\\n" +\n-            "  -addnode=<ip>    \\t  "   + _("Add a node to connect to") + "\\n" +\n+            "  -addnode=<ip>    \\t  "   + _("Add a node to connect to and attempt to keep the connection open") + "\\n" +\n             "  -connect=<ip>    \\t\\t  " + _("Connect only to the specified node") + "\\n" +\n             "  -noirc           \\t  "   + _("Don\'t find peers using internet relay chat") + "\\n" +\n             "  -nolisten        \\t  "   + _("Don\'t accept connections from outside") + "\\n" +\ndiff --git a/src/net.cpp b/src/net.cpp\nindex 817203b01..cdd72fddd 100644\n--- a/src/net.cpp\n+++ b/src/net.cpp\n@@ -29,6 +29,7 @@ static const int MAX_OUTBOUND_CONNECTIONS = 8;\n void ThreadMessageHandler2(void* parg);\n void ThreadSocketHandler2(void* parg);\n void ThreadOpenConnections2(void* parg);\n+void ThreadOpenAddedConnections2(void* parg);\n #ifdef USE_UPNP\n void ThreadMapPort2(void* parg);\n #endif\n@@ -61,6 +62,9 @@ CCriticalSection cs_mapRelay;\n map<CInv, int64> mapAlreadyAskedFor;\n \n \n+set<CNetAddr> setservAddNodeAddresses;\n+CCriticalSection cs_setservAddNodeAddresses;\n+\n \n \n \n@@ -750,7 +754,9 @@ void ThreadSocketHandler2(void* parg)\n             }\n             else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)\n             {\n-                closesocket(hSocket);\n+                CRITICAL_BLOCK(cs_setservAddNodeAddresses)\n+                    if (!setservAddNodeAddresses.count(addr))\n+                        closesocket(hSocket);\n             }\n             else if (CNode::IsBanned(addr))\n             {\n@@ -1211,22 +1217,6 @@ void ThreadOpenConnections2(void* parg)\n         }\n     }\n \n-    // Connect to manually added nodes first\n-    if (mapArgs.count("-addnode"))\n-    {\n-        BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])\n-        {\n-            CAddress addr(strAddr, fAllowDNS);\n-            if (addr.IsValid())\n-            {\n-                OpenNetworkConnection(addr);\n-                Sleep(500);\n-                if (fShutdown)\n-                    return;\n-            }\n-        }\n-    }\n-\n     // Initiate network connections\n     int64 nStart = GetTime();\n     loop\n@@ -1355,6 +1345,76 @@ void ThreadOpenConnections2(void* parg)\n     }\n }\n \n+void ThreadOpenAddedConnections(void* parg)\n+{\n+    IMPLEMENT_RANDOMIZE_STACK(ThreadOpenAddedConnections(parg));\n+    try\n+    {\n+        vnThreadsRunning[7]++;\n+        ThreadOpenAddedConnections2(parg);\n+        vnThreadsRunning[7]--;\n+    }\n+    catch (std::exception& e) {\n+        vnThreadsRunning[7]--;\n+        PrintException(&e, "ThreadOpenAddedConnections()");\n+    } catch (...) {\n+        vnThreadsRunning[7]--;\n+        PrintException(NULL, "ThreadOpenAddedConnections()");\n+    }\n+    printf("ThreadOpenAddedConnections exiting\\n");\n+}\n+\n+void ThreadOpenAddedConnections2(void* parg)\n+{\n+    printf("ThreadOpenAddedConnections started\\n");\n+\n+    if (mapArgs.count("-addnode") == 0)\n+        return;\n+\n+    vector<vector<CService> > vservAddressesToAdd(0);\n+    BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"])\n+    {\n+        vector<CService> vservNode(0);\n+        if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fAllowDNS, 0))\n+        {\n+            vservAddressesToAdd.push_back(vservNode);\n+            CRITICAL_BLOCK(cs_setservAddNodeAddresses)\n+                BOOST_FOREACH(CService& serv, vservNode)\n+                    setservAddNodeAddresses.insert(serv);\n+        }\n+    }\n+    loop\n+    {\n+        vector<vector<CService> > vservConnectAddresses = vservAddressesToAdd;\n+        // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry\n+        // (keeping in mind that addnode entries can have many IPs if fAllowDNS)\n+        CRITICAL_BLOCK(cs_vNodes)\n+            BOOST_FOREACH(CNode* pnode, vNodes)\n+                for (vector<vector<CService> >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++)\n+                    BOOST_FOREACH(CService& addrNode, *(it))\n+                        if (pnode->addr == addrNode)\n+                        {\n+                            it = vservConnectAddresses.erase(it);\n+                            it--;\n+                            break;\n+                        }\n+        BOOST_FOREACH(vector<CService>& vserv, vservConnectAddresses)\n+        {\n+            OpenNetworkConnection(CAddress(*(vserv.begin())));\n+            Sleep(500);\n+            if (fShutdown)\n+                return;\n+        }\n+        if (fShutdown)\n+            return;\n+        vnThreadsRunning[7]--;\n+        Sleep(120000); // Retry every 2 minutes\n+        vnThreadsRunning[7]++;\n+        if (fShutdown)\n+            return;\n+    }\n+}\n+\n bool OpenNetworkConnection(const CAddress& addrConnect)\n {\n     //\n@@ -1631,6 +1691,10 @@ void StartNode(void* parg)\n     if (!CreateThread(ThreadSocketHandler, NULL))\n         printf("Error: CreateThread(ThreadSocketHandler) failed\\n");\n \n+    // Initiate outbound connections from -addnode\n+    if (!CreateThread(ThreadOpenAddedConnections, NULL))\n+        printf("Error: CreateThread(ThreadOpenAddedConnections) failed\\n");\n+\n     // Initiate outbound connections\n     if (!CreateThread(ThreadOpenConnections, NULL))\n         printf("Error: CreateThread(ThreadOpenConnections) failed\\n");\n@@ -1650,9 +1714,7 @@ bool StopNode()\n     nTransactionsUpdated++;\n     int64 nStart = GetTime();\n     while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0\n-#ifdef USE_UPNP\n-        || vnThreadsRunning[5] > 0\n-#endif\n+        || (fHaveUPnP && vnThreadsRunning[5] > 0) || vnThreadsRunning[6] > 0 || vnThreadsRunning[7] > 0\n     )\n     {\n         if (GetTime() - nStart > 20)\n@@ -1666,6 +1728,7 @@ bool StopNode()\n     if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\\n");\n     if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\\n");\n     if (vnThreadsRunning[6] > 0) printf("ThreadDNSAddressSeed still running\\n");\n+    if (vnThreadsRunning[7] > 0) printf("ThreadOpenAddedConnections still running\\n");\n     while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)\n         Sleep(20);\n     Sleep(50);\ndiff --git a/src/netbase.cpp b/src/netbase.cpp\nindex ca27c2a8c..48db3625c 100644\n--- a/src/netbase.cpp\n+++ b/src/netbase.cpp\n@@ -98,7 +98,7 @@ bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, int nMax\n     return LookupHost(pszName, vIP, nMaxSolutions, false);\n }\n \n-bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup)\n+bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, int nMaxSolutions)\n {\n     if (pszName[0] == 0)\n         return false;\n@@ -132,10 +132,22 @@ bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLoo\n     }\n \n     std::vector<CNetAddr> vIP;\n-    bool fRet = LookupIntern(pszHost, vIP, 1, fAllowLookup);\n+    bool fRet = LookupIntern(pszHost, vIP, nMaxSolutions, fAllowLookup);\n+    if (!fRet)\n+        return false;\n+    vAddr.resize(vIP.size());\n+    for (int i = 0; i < vIP.size(); i++)\n+        vAddr[i] = CService(vIP[i], port);\n+    return true;\n+}\n+\n+bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup)\n+{\n+    std::vector<CService> vService;\n+    bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1);\n     if (!fRet)\n         return false;\n-    addr = CService(vIP[0], port);\n+    addr = vService[0];\n     return true;\n }\n \ndiff --git a/src/netbase.h b/src/netbase.h\nindex 6f06f8fe0..b12fb0045 100644\n--- a/src/netbase.h\n+++ b/src/netbase.h\n@@ -128,6 +128,7 @@ class CService : public CNetAddr\n bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0, bool fAllowLookup = true);\n bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0);\n bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);\n+bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault = 0, bool fAllowLookup = true, int nMaxSolutions = 0);\n bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);\n bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout);\n \n', 'commit_subject': "Merge branch 'keepnode' of https://github.com/TheBlueMatt/bitcoin", 'repo_name': 'zcoinofficial/zcoin', 'committer': {'name': 'Gavin Andresen', 'email': '19a45ba432ebf68c5c553ec17ef341bff6a9e1b9@gmail.com', 'time_sec': '1326750343', 'tz_offset': '-300', 'date': {'seconds': '1326750343'}}, 'commit_tree': '5084f2fedb69b5c3a58e2ea915b27adbf189c0e0', 'commit_message': "Merge branch 'keepnode' of https://github.com/TheBlueMatt/bitcoin\n", 'language_name': 'HTML', 'license': 'mit', 'hunks': '@@ -128,6 +128,7 @@ class CService : public CNetAddr\n bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0, bool fAllowLookup = true);\n bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0);\n bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);\n+bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault = 0, bool fAllowLookup = true, int nMaxSolutions = 0);\n bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);\n bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout);\n \n', 'addition_count': 1, 'deletion_count': 0, 'src_file': 'a/src/netbase.h', 'tgt_file': 'b/src/netbase.h', 'file_extension': '.h', 'before_file': '// Copyright (c) 2009-2016 The Bitcoin Core developers\n// Distributed under the MIT software license, see the accompanying\n// file COPYING or http://www.opensource.org/licenses/mit-license.php.\n\n#ifndef BITCOIN_NETBASE_H\n#define BITCOIN_NETBASE_H\n\n#if defined(HAVE_CONFIG_H)\n#include "config/bitcoin-config.h"\n#endif\n\n#include "compat.h"\n#include "netaddress.h"\n#include "serialize.h"\n\n#include <stdint.h>\n#include <string>\n#include <vector>\n\nextern int nConnectTimeout;\nextern bool fNameLookup;\n\n//! -timeout default\nstatic const int DEFAULT_CONNECT_TIMEOUT = 5000;\n//! -dns default\nstatic const int DEFAULT_NAME_LOOKUP = true;\n\nclass proxyType\n{\npublic:\n    proxyType(): randomize_credentials(false) {}\n    proxyType(const CService &_proxy, bool _randomize_credentials=false): proxy(_proxy), randomize_credentials(_randomize_credentials) {}\n\n    bool IsValid() const { return proxy.IsValid(); }\n\n    CService proxy;\n    bool randomize_credentials;\n};\n\nenum Network ParseNetwork(std::string net);\nstd::string GetNetworkName(enum Network net);\nvoid SplitHostPort(std::string in, int &portOut, std::string &hostOut);\nbool SetProxy(enum Network net, const proxyType &addrProxy);\nbool GetProxy(enum Network net, proxyType &proxyInfoOut);\nbool IsProxy(const CNetAddr &addr);\nbool SetNameProxy(const proxyType &addrProxy);\nbool HaveNameProxy();\nbool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup);\nbool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup);\nbool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup);\nbool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions);\nCService LookupNumeric(const char *pszName, int portDefault = 0);\nbool LookupSubNet(const char *pszName, CSubNet& subnet);\nbool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0);\nbool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0);\n/** Return readable error string for a network error code */\nstd::string NetworkErrorString(int err);\n/** Close socket and set hSocket to INVALID_SOCKET */\nbool CloseSocket(SOCKET& hSocket);\n/** Disable or enable blocking-mode for a socket */\nbool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking);\n/**\n * Convert milliseconds to a struct timeval for e.g. select.\n */\nstruct timeval MillisToTimeval(int64_t nTimeout);\nvoid InterruptSocks5(bool interrupt);\n\n#endif // BITCOIN_NETBASE_H\nbool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0, bool fAllowLookup = true);\nbool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, int nMaxSolutions = 0);\nbool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);\nbool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);\nbool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout);\n\n', 'message': "Merge branch 'keepnode' of https://github.com/TheBlueMatt/bitcoin\n", 'author_name': 'Gavin Andresen', 'lang': 'h'}