changeset 3599:837b10c010b6 draft

Merge pull request #1859 from Diapolo/proxy_locks add LOCK() for proxy related data-structures
author Pieter Wuille <pieter.wuille@gmail.com>
date Sun, 07 Oct 2012 07:03:06 -0700
parents 5a7e013bf2e7 (current diff) 9e976381e5ba (diff)
children ac8d4b1e089a a3ef3e3e0ee2 af357503c973
files src/rpcwallet.cpp
diffstat 5 files changed, 77 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1185,7 +1185,7 @@
         printf("Loading addresses from DNS seeds (could take a while)\n");
 
         for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
-            if (GetNameProxy()) {
+            if (HaveNameProxy()) {
                 AddOneShot(strDNSSeed[seed_idx][1]);
             } else {
                 vector<CNetAddr> vaddr;
@@ -1529,7 +1529,7 @@
     if (mapArgs.count("-addnode") == 0)
         return;
 
-    if (GetNameProxy()) {
+    if (HaveNameProxy()) {
         while(!fShutdown) {
             BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"]) {
                 CAddress addr;
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -5,6 +5,7 @@
 
 #include "netbase.h"
 #include "util.h"
+#include "sync.h"
 
 #ifndef WIN32
 #include <sys/fcntl.h>
@@ -16,9 +17,9 @@
 using namespace std;
 
 // Settings
-typedef std::pair<CService, int> proxyType;
 static proxyType proxyInfo[NET_MAX];
 static proxyType nameproxyInfo;
+static CCriticalSection cs_proxyInfos;
 int nConnectTimeout = 5000;
 bool fNameLookup = false;
 
@@ -432,15 +433,17 @@
         return false;
     if (nSocksVersion != 0 && !addrProxy.IsValid())
         return false;
+    LOCK(cs_proxyInfos);
     proxyInfo[net] = std::make_pair(addrProxy, nSocksVersion);
     return true;
 }
 
-bool GetProxy(enum Network net, CService &addrProxy) {
+bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
     assert(net >= 0 && net < NET_MAX);
+    LOCK(cs_proxyInfos);
     if (!proxyInfo[net].second)
         return false;
-    addrProxy = proxyInfo[net].first;
+    proxyInfoOut = proxyInfo[net];
     return true;
 }
 
@@ -449,16 +452,27 @@
         return false;
     if (nSocksVersion != 0 && !addrProxy.IsValid())
         return false;
+    LOCK(cs_proxyInfos);
     nameproxyInfo = std::make_pair(addrProxy, nSocksVersion);
     return true;
 }
 
-bool GetNameProxy() {
+bool GetNameProxy(proxyType &nameproxyInfoOut) {
+    LOCK(cs_proxyInfos);
+    if (!nameproxyInfo.second)
+        return false;
+    nameproxyInfoOut = nameproxyInfo;
+    return true;
+}
+
+bool HaveNameProxy() {
+    LOCK(cs_proxyInfos);
     return nameproxyInfo.second != 0;
 }
 
 bool IsProxy(const CNetAddr &addr) {
-    for (int i=0; i<NET_MAX; i++) {
+    LOCK(cs_proxyInfos);
+    for (int i = 0; i < NET_MAX; i++) {
         if (proxyInfo[i].second && (addr == (CNetAddr)proxyInfo[i].first))
             return true;
     }
@@ -467,10 +481,10 @@
 
 bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
 {
-    const proxyType &proxy = proxyInfo[addrDest.GetNetwork()];
+    proxyType proxy;
 
     // no proxy needed
-    if (!proxy.second)
+    if (!GetProxy(addrDest.GetNetwork(), proxy))
         return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout);
 
     SOCKET hSocket = INVALID_SOCKET;
@@ -504,19 +518,22 @@
     SplitHostPort(string(pszDest), port, strDest);
 
     SOCKET hSocket = INVALID_SOCKET;
-    CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxyInfo.second), port);
+
+    proxyType nameproxy;
+    GetNameProxy(nameproxy);
+
+    CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxy.second), port);
     if (addrResolved.IsValid()) {
         addr = addrResolved;
         return ConnectSocket(addr, hSocketRet, nTimeout);
     }
     addr = CService("0.0.0.0:0");
-    if (!nameproxyInfo.second)
+    if (!nameproxy.second)
         return false;
-    if (!ConnectSocketDirectly(nameproxyInfo.first, hSocket, nTimeout))
+    if (!ConnectSocketDirectly(nameproxy.first, hSocket, nTimeout))
         return false;
 
-    switch(nameproxyInfo.second)
-    {
+    switch(nameproxy.second) {
         default:
         case 4: return false;
         case 5:
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -133,13 +133,15 @@
             )
 };
 
+typedef std::pair<CService, int> proxyType;
+
 enum Network ParseNetwork(std::string net);
 void SplitHostPort(std::string in, int &portOut, std::string &hostOut);
 bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion = 5);
-bool GetProxy(enum Network net, CService &addrProxy);
+bool GetProxy(enum Network net, proxyType &proxyInfoOut);
 bool IsProxy(const CNetAddr &addr);
 bool SetNameProxy(CService addrProxy, int nSocksVersion = 5);
-bool GetNameProxy();
+bool HaveNameProxy();
 bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true);
 bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0);
 bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -145,18 +145,18 @@
         case ProxyUse:
             return settings.value("fUseProxy", false);
         case ProxyIP: {
-            CService addrProxy;
-            if (GetProxy(NET_IPV4, addrProxy))
-                return QVariant(QString::fromStdString(addrProxy.ToStringIP()));
+            proxyType proxy;
+            if (GetProxy(NET_IPV4, proxy))
+                return QVariant(QString::fromStdString(proxy.first.ToStringIP()));
             else
                 return QVariant(QString::fromStdString("127.0.0.1"));
         }
         case ProxyPort: {
-            CService addrProxy;
-            if (GetProxy(NET_IPV4, addrProxy))
-                return QVariant(addrProxy.GetPort());
+            proxyType proxy;
+            if (GetProxy(NET_IPV4, proxy))
+                return QVariant(proxy.first.GetPort());
             else
-                return 9050;
+                return QVariant(9050);
         }
         case ProxySocksVersion:
             return settings.value("nSocksVersion", 5);
@@ -176,6 +176,7 @@
     }
     return QVariant();
 }
+
 bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, int role)
 {
     bool successful = true; /* set to false on parse error */
@@ -204,29 +205,37 @@
             settings.setValue("fUseProxy", value.toBool());
             ApplyProxySettings();
             break;
-        case ProxyIP:
-            {
-                CService addrProxy("127.0.0.1", 9050);
-                GetProxy(NET_IPV4, addrProxy);
-                CNetAddr addr(value.toString().toStdString());
-                addrProxy.SetIP(addr);
-                settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str());
-                successful = ApplyProxySettings();
-            }
-            break;
-        case ProxyPort:
-            {
-                CService addrProxy("127.0.0.1", 9050);
-                GetProxy(NET_IPV4, addrProxy);
-                addrProxy.SetPort(value.toInt());
-                settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str());
-                successful = ApplyProxySettings();
-            }
-            break;
-        case ProxySocksVersion:
-            settings.setValue("nSocksVersion", value.toInt());
-            ApplyProxySettings();
-            break;
+        case ProxyIP: {
+            proxyType proxy;
+            proxy.first = CService("127.0.0.1", 9050);
+            GetProxy(NET_IPV4, proxy);
+
+            CNetAddr addr(value.toString().toStdString());
+            proxy.first.SetIP(addr);
+            settings.setValue("addrProxy", proxy.first.ToStringIPPort().c_str());
+            successful = ApplyProxySettings();
+        }
+        break;
+        case ProxyPort: {
+            proxyType proxy;
+            proxy.first = CService("127.0.0.1", 9050);
+            GetProxy(NET_IPV4, proxy);
+
+            proxy.first.SetPort(value.toInt());
+            settings.setValue("addrProxy", proxy.first.ToStringIPPort().c_str());
+            successful = ApplyProxySettings();
+        }
+        break;
+        case ProxySocksVersion: {
+            proxyType proxy;
+            proxy.second = 5;
+            GetProxy(NET_IPV4, proxy);
+
+            proxy.second = value.toInt();
+            settings.setValue("nSocksVersion", proxy.second);
+            successful = ApplyProxySettings();
+        }
+        break;
         case Fee:
             nTransactionFee = value.toLongLong();
             settings.setValue("nTransactionFee", nTransactionFee);
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -62,8 +62,8 @@
             "getinfo\n"
             "Returns an object containing various state info.");
 
-    CService addrProxy;
-    GetProxy(NET_IPV4, addrProxy);
+    proxyType proxy;
+    GetProxy(NET_IPV4, proxy);
 
     Object obj;
     obj.push_back(Pair("version",       (int)CLIENT_VERSION));
@@ -72,7 +72,7 @@
     obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
     obj.push_back(Pair("blocks",        (int)nBestHeight));
     obj.push_back(Pair("connections",   (int)vNodes.size()));
-    obj.push_back(Pair("proxy",         (addrProxy.IsValid() ? addrProxy.ToStringIPPort() : string())));
+    obj.push_back(Pair("proxy",         (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
     obj.push_back(Pair("difficulty",    (double)GetDifficulty()));
     obj.push_back(Pair("testnet",       fTestNet));
     obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));