This commit is contained in:
Gavin Andresen 2012-06-04 14:15:19 -04:00
commit 46e06b875d
11 changed files with 237 additions and 164 deletions

View File

@ -531,6 +531,9 @@ Value getinfo(const Array& params, bool fHelp)
"getinfo\n" "getinfo\n"
"Returns an object containing various state info."); "Returns an object containing various state info.");
CService addrProxy;
GetProxy(NET_IPV4, addrProxy);
Object obj; Object obj;
obj.push_back(Pair("version", (int)CLIENT_VERSION)); obj.push_back(Pair("version", (int)CLIENT_VERSION));
obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
@ -538,7 +541,7 @@ Value getinfo(const Array& params, bool fHelp)
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
obj.push_back(Pair("blocks", (int)nBestHeight)); obj.push_back(Pair("blocks", (int)nBestHeight));
obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string()))); obj.push_back(Pair("proxy", (addrProxy.IsValid() ? addrProxy.ToStringIPPort() : string())));
obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("testnet", fTestNet)); obj.push_back(Pair("testnet", fTestNet));
obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime())); obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));

View File

@ -182,12 +182,15 @@ bool static InitWarning(const std::string &str)
} }
bool static Bind(const CService &addr) { bool static Bind(const CService &addr, bool fError = true) {
if (IsLimited(addr)) if (IsLimited(addr))
return false; return false;
std::string strError; std::string strError;
if (!BindListenPort(addr, strError)) if (!BindListenPort(addr, strError)) {
return InitError(strError); if (fError)
return InitError(strError);
return false;
}
return true; return true;
} }
@ -204,20 +207,18 @@ std::string HelpMessage()
" -dblogsize=<n> " + _("Set database disk log size in megabytes (default: 100)") + "\n" + " -dblogsize=<n> " + _("Set database disk log size in megabytes (default: 100)") + "\n" +
" -timeout=<n> " + _("Specify connection timeout (in milliseconds)") + "\n" + " -timeout=<n> " + _("Specify connection timeout (in milliseconds)") + "\n" +
" -proxy=<ip:port> " + _("Connect through socks proxy") + "\n" + " -proxy=<ip:port> " + _("Connect through socks proxy") + "\n" +
" -socks=<n> " + _("Select the version of socks proxy to use (4 or 5, 5 is default)") + "\n" + " -socks=<n> " + _("Select the version of socks proxy to use (4-5, default: 5)") + "\n" +
" -noproxy=<net> " + _("Do not use proxy for connections to network <net> (IPv4 or IPv6)") + "\n" +
" -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" + " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" +
" -proxydns " + _("Pass DNS requests to (SOCKS5) proxy") + "\n" +
" -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n" + " -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n" +
" -maxconnections=<n> " + _("Maintain at most <n> connections to peers (default: 125)") + "\n" + " -maxconnections=<n> " + _("Maintain at most <n> connections to peers (default: 125)") + "\n" +
" -addnode=<ip> " + _("Add a node to connect to and attempt to keep the connection open") + "\n" + " -addnode=<ip> " + _("Add a node to connect to and attempt to keep the connection open") + "\n" +
" -connect=<ip> " + _("Connect only to the specified node") + "\n" + " -connect=<ip> " + _("Connect only to the specified node(s)") + "\n" +
" -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n" + " -seednode=<ip> " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n" +
" -externalip=<ip> " + _("Specify your own public address") + "\n" + " -externalip=<ip> " + _("Specify your own public address") + "\n" +
" -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4 or IPv6)") + "\n" + " -onlynet=<net> " + _("Only connect to nodes in network <net> (IPv4 or IPv6)") + "\n" +
" -discover " + _("Try to discover public IP address (default: 1)") + "\n" + " -discover " + _("Discover own IP address (default: 1 when listening and no -externalip)") + "\n" +
" -irc " + _("Find peers using internet relay chat (default: 0)") + "\n" + " -irc " + _("Find peers using internet relay chat (default: 0)") + "\n" +
" -listen " + _("Accept connections from outside (default: 1)") + "\n" + " -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n" +
" -bind=<addr> " + _("Bind to given address. Use [host]:port notation for IPv6") + "\n" + " -bind=<addr> " + _("Bind to given address. Use [host]:port notation for IPv6") + "\n" +
" -dnsseed " + _("Find peers using DNS lookup (default: 1)") + "\n" + " -dnsseed " + _("Find peers using DNS lookup (default: 1)") + "\n" +
" -banscore=<n> " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" + " -banscore=<n> " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" +
@ -226,9 +227,9 @@ std::string HelpMessage()
" -maxsendbuffer=<n> " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)") + "\n" + " -maxsendbuffer=<n> " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)") + "\n" +
#ifdef USE_UPNP #ifdef USE_UPNP
#if USE_UPNP #if USE_UPNP
" -upnp " + _("Use Universal Plug and Play to map the listening port (default: 1)") + "\n" + " -upnp " + _("Use UPnP to map the listening port (default: 1 when listening)") + "\n" +
#else #else
" -upnp " + _("Use Universal Plug and Play to map the listening port (default: 0)") + "\n" + " -upnp " + _("Use UPnP to map the listening port (default: 0)") + "\n" +
#endif #endif
#endif #endif
" -detachdb " + _("Detach block and address databases. Increases shutdown time (default: 0)") + "\n" + " -detachdb " + _("Detach block and address databases. Increases shutdown time (default: 0)") + "\n" +
@ -308,30 +309,38 @@ bool AppInit2()
// ********************************************************* Step 2: parameter interactions // ********************************************************* Step 2: parameter interactions
fTestNet = GetBoolArg("-testnet"); fTestNet = GetBoolArg("-testnet");
if (fTestNet) if (fTestNet) {
{
SoftSetBoolArg("-irc", true); SoftSetBoolArg("-irc", true);
} }
if (mapArgs.count("-connect")) if (mapArgs.count("-bind")) {
SoftSetBoolArg("-dnsseed", false); // when specifying an explicit binding address, you want to listen on it
// even when -connect or -proxy is specified
// even in Tor mode, if -bind is specified, you really want -listen
if (mapArgs.count("-bind"))
SoftSetBoolArg("-listen", true); SoftSetBoolArg("-listen", true);
}
bool fTor = (fUseProxy && addrProxy.GetPort() == 9050); if (mapArgs.count("-connect")) {
if (fTor) // when only connecting to trusted nodes, do not seed via DNS, or listen by default
{ SoftSetBoolArg("-dnsseed", false);
// Use SoftSetBoolArg here so user can override any of these if they wish.
// Note: the GetBoolArg() calls for all of these must happen later.
SoftSetBoolArg("-listen", false); SoftSetBoolArg("-listen", false);
SoftSetBoolArg("-irc", false); }
SoftSetBoolArg("-proxydns", true);
if (mapArgs.count("-proxy")) {
// to protect privacy, do not listen by default if a proxy server is specified
SoftSetBoolArg("-listen", false);
}
if (GetBoolArg("-listen", true)) {
// do not map ports or try to retrieve public IP when not listening (pointless)
SoftSetBoolArg("-upnp", false); SoftSetBoolArg("-upnp", false);
SoftSetBoolArg("-discover", false); SoftSetBoolArg("-discover", false);
} }
if (mapArgs.count("-externalip")) {
// if an explicit public IP is specified, do not try to find others
SoftSetBoolArg("-discover", false);
}
// ********************************************************* Step 3: parameter-to-internal-flags // ********************************************************* Step 3: parameter-to-internal-flags
fDebug = GetBoolArg("-debug"); fDebug = GetBoolArg("-debug");
@ -425,30 +434,8 @@ bool AppInit2()
// ********************************************************* Step 5: network initialization // ********************************************************* Step 5: network initialization
if (mapArgs.count("-proxy")) int nSocksVersion = GetArg("-socks", 5);
{
fUseProxy = true;
addrProxy = CService(mapArgs["-proxy"], 9050);
if (!addrProxy.IsValid())
return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"].c_str()));
}
if (mapArgs.count("-noproxy"))
{
BOOST_FOREACH(std::string snet, mapMultiArgs["-noproxy"]) {
enum Network net = ParseNetwork(snet);
if (net == NET_UNROUTABLE)
return InitError(strprintf(_("Unknown network specified in -noproxy: '%s'"), snet.c_str()));
SetNoProxy(net);
}
}
fNameLookup = GetBoolArg("-dns");
fProxyNameLookup = GetBoolArg("-proxydns");
if (fProxyNameLookup)
fNameLookup = true;
fNoListen = !GetBoolArg("-listen", true);
nSocksVersion = GetArg("-socks", 5);
if (nSocksVersion != 4 && nSocksVersion != 5) if (nSocksVersion != 4 && nSocksVersion != 5)
return InitError(strprintf(_("Unknown -socks proxy version requested: %i"), nSocksVersion)); return InitError(strprintf(_("Unknown -socks proxy version requested: %i"), nSocksVersion));
@ -467,8 +454,29 @@ bool AppInit2()
} }
} }
BOOST_FOREACH(string strDest, mapMultiArgs["-seednode"]) if (mapArgs.count("-proxy")) {
AddOneShot(strDest); CService addrProxy = CService(mapArgs["-proxy"], 9050);
if (!addrProxy.IsValid())
return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"].c_str()));
if (!IsLimited(NET_IPV4))
SetProxy(NET_IPV4, addrProxy, nSocksVersion);
if (nSocksVersion > 4) {
#ifdef USE_IPV6
if (!IsLimited(NET_IPV6))
SetProxy(NET_IPV6, addrProxy, nSocksVersion);
#endif
SetNameProxy(addrProxy, nSocksVersion);
}
}
// see Step 2: parameter interactions for more information about these
fNoListen = !GetBoolArg("-listen", true);
fDiscover = GetBoolArg("-discover", true);
fNameLookup = GetBoolArg("-dns", true);
#ifdef USE_UPNP
fUseUPnP = GetBoolArg("-upnp", USE_UPNP);
#endif
bool fBound = false; bool fBound = false;
if (!fNoListen) if (!fNoListen)
@ -484,15 +492,15 @@ bool AppInit2()
} else { } else {
struct in_addr inaddr_any; struct in_addr inaddr_any;
inaddr_any.s_addr = INADDR_ANY; inaddr_any.s_addr = INADDR_ANY;
if (!IsLimited(NET_IPV4))
fBound |= Bind(CService(inaddr_any, GetListenPort()));
#ifdef USE_IPV6 #ifdef USE_IPV6
if (!IsLimited(NET_IPV6)) if (!IsLimited(NET_IPV6))
fBound |= Bind(CService(in6addr_any, GetListenPort())); fBound |= Bind(CService(in6addr_any, GetListenPort()), false);
#endif #endif
if (!IsLimited(NET_IPV4))
fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound);
} }
if (!fBound) if (!fBound)
return InitError(_("Not listening on any port")); return InitError(_("Failed to listen on any port. Use -listen=0 if you want this."));
} }
if (mapArgs.count("-externalip")) if (mapArgs.count("-externalip"))
@ -505,6 +513,9 @@ bool AppInit2()
} }
} }
BOOST_FOREACH(string strDest, mapMultiArgs["-seednode"])
AddOneShot(strDest);
// ********************************************************* Step 6: load blockchain // ********************************************************* Step 6: load blockchain
if (GetBoolArg("-loadblockindextest")) if (GetBoolArg("-loadblockindextest"))

View File

@ -176,8 +176,6 @@ bool GetIPFromIRC(SOCKET hSocket, string strMyName, CNetAddr& ipRet)
// Hybrid IRC used by lfnet always returns IP when you userhost yourself, // Hybrid IRC used by lfnet always returns IP when you userhost yourself,
// but in case another IRC is ever used this should work. // but in case another IRC is ever used this should work.
printf("GetIPFromIRC() got userhost %s\n", strHost.c_str()); printf("GetIPFromIRC() got userhost %s\n", strHost.c_str());
if (fUseProxy)
return false;
CNetAddr addr(strHost, true); CNetAddr addr(strHost, true);
if (!addr.IsValid()) if (!addr.IsValid())
return false; return false;
@ -281,7 +279,7 @@ void ThreadIRCSeed2(void* parg)
if (GetIPFromIRC(hSocket, strMyName, addrFromIRC)) if (GetIPFromIRC(hSocket, strMyName, addrFromIRC))
{ {
printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToString().c_str()); printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToString().c_str());
if (!fUseProxy && addrFromIRC.IsRoutable()) if (addrFromIRC.IsRoutable())
{ {
// IRC lets you to re-nick // IRC lets you to re-nick
AddLocal(addrFromIRC, LOCAL_IRC); AddLocal(addrFromIRC, LOCAL_IRC);

View File

@ -2377,7 +2377,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (!pfrom->fInbound) if (!pfrom->fInbound)
{ {
// Advertise our address // Advertise our address
if (!fNoListen && !fUseProxy && !IsInitialBlockDownload()) if (!fNoListen && !IsInitialBlockDownload())
{ {
CAddress addr = GetLocalAddress(&pfrom->addr); CAddress addr = GetLocalAddress(&pfrom->addr);
if (addr.IsRoutable()) if (addr.IsRoutable())
@ -3035,7 +3035,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
pnode->setAddrKnown.clear(); pnode->setAddrKnown.clear();
// Rebroadcast our address // Rebroadcast our address
if (!fNoListen && !fUseProxy) if (!fNoListen)
{ {
CAddress addr = GetLocalAddress(&pnode->addr); CAddress addr = GetLocalAddress(&pnode->addr);
if (addr.IsRoutable()) if (addr.IsRoutable())

View File

@ -47,7 +47,8 @@ struct LocalServiceInfo {
// Global state variables // Global state variables
// //
bool fClient = false; bool fClient = false;
static bool fUseUPnP = false; bool fDiscover = true;
bool fUseUPnP = false;
uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK); uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
static CCriticalSection cs_mapLocalHost; static CCriticalSection cs_mapLocalHost;
static map<CNetAddr, LocalServiceInfo> mapLocalHost; static map<CNetAddr, LocalServiceInfo> mapLocalHost;
@ -99,7 +100,7 @@ void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
// find 'best' local address for a particular peer // find 'best' local address for a particular peer
bool GetLocal(CService& addr, const CNetAddr *paddrPeer) bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
{ {
if (fUseProxy || mapArgs.count("-connect") || fNoListen) if (fNoListen)
return false; return false;
int nBestScore = -1; int nBestScore = -1;
@ -211,7 +212,7 @@ bool AddLocal(const CService& addr, int nScore)
if (!addr.IsRoutable()) if (!addr.IsRoutable())
return false; return false;
if (!GetBoolArg("-discover", true) && nScore < LOCAL_MANUAL) if (!fDiscover && nScore < LOCAL_MANUAL)
return false; return false;
if (IsLimited(addr)) if (IsLimited(addr))
@ -345,9 +346,6 @@ bool GetMyExternalIP(CNetAddr& ipRet)
const char* pszGet; const char* pszGet;
const char* pszKeyword; const char* pszKeyword;
if (fNoListen||fUseProxy)
return false;
for (int nLookup = 0; nLookup <= 1; nLookup++) for (int nLookup = 0; nLookup <= 1; nLookup++)
for (int nHost = 1; nHost <= 2; nHost++) for (int nHost = 1; nHost <= 2; nHost++)
{ {
@ -542,7 +540,7 @@ void CNode::PushVersion()
{ {
/// when NTP implemented, change to just nTime = GetAdjustedTime() /// when NTP implemented, change to just nTime = GetAdjustedTime()
int64 nTime = (fInbound ? GetAdjustedTime() : GetTime()); int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
CAddress addrYou = (fUseProxy ? CAddress(CService("0.0.0.0",0)) : addr); CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
CAddress addrMe = GetLocalAddress(&addr); CAddress addrMe = GetLocalAddress(&addr);
RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
@ -1016,7 +1014,7 @@ void ThreadMapPort2(void* parg)
r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
if (r == 1) if (r == 1)
{ {
if (GetBoolArg("-discover", true)) { if (fDiscover) {
char externalIPAddress[40]; char externalIPAddress[40];
r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress); r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
if(r != UPNPCOMMAND_SUCCESS) if(r != UPNPCOMMAND_SUCCESS)
@ -1093,12 +1091,8 @@ void ThreadMapPort2(void* parg)
} }
} }
void MapPort(bool fMapPort) void MapPort()
{ {
if (fUseUPnP != fMapPort)
{
fUseUPnP = fMapPort;
}
if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1) if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
{ {
if (!CreateThread(ThreadMapPort, NULL)) if (!CreateThread(ThreadMapPort, NULL))
@ -1106,7 +1100,7 @@ void MapPort(bool fMapPort)
} }
} }
#else #else
void MapPort(bool /* unused fMapPort */) void MapPort()
{ {
// Intentionally left blank. // Intentionally left blank.
} }
@ -1160,7 +1154,7 @@ void ThreadDNSAddressSeed2(void* parg)
printf("Loading addresses from DNS seeds (could take a while)\n"); printf("Loading addresses from DNS seeds (could take a while)\n");
for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) { for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
if (fProxyNameLookup) { if (GetNameProxy()) {
AddOneShot(strDNSSeed[seed_idx][1]); AddOneShot(strDNSSeed[seed_idx][1]);
} else { } else {
vector<CNetAddr> vaddr; vector<CNetAddr> vaddr;
@ -1394,8 +1388,7 @@ void ThreadOpenConnections2(void* parg)
return; return;
// Add seed nodes if IRC isn't working // Add seed nodes if IRC isn't working
bool fTOR = (fUseProxy && addrProxy.GetPort() == 9050); if (addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
if (addrman.size()==0 && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
{ {
std::vector<CAddress> vAdd; std::vector<CAddress> vAdd;
for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++) for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
@ -1492,7 +1485,7 @@ void ThreadOpenAddedConnections2(void* parg)
if (mapArgs.count("-addnode") == 0) if (mapArgs.count("-addnode") == 0)
return; return;
if (fProxyNameLookup) { if (GetNameProxy()) {
while(!fShutdown) { while(!fShutdown) {
BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"]) { BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"]) {
CAddress addr; CAddress addr;
@ -1778,7 +1771,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
vhListenSocket.push_back(hListenSocket); vhListenSocket.push_back(hListenSocket);
if (addrBind.IsRoutable() && GetBoolArg("-discover", true)) if (addrBind.IsRoutable() && fDiscover)
AddLocal(addrBind, LOCAL_BIND); AddLocal(addrBind, LOCAL_BIND);
return true; return true;
@ -1786,7 +1779,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
void static Discover() void static Discover()
{ {
if (!GetBoolArg("-discover", true)) if (!fDiscover)
return; return;
#ifdef WIN32 #ifdef WIN32
@ -1835,22 +1828,11 @@ void static Discover()
} }
#endif #endif
if (!fUseProxy && !mapArgs.count("-connect") && !fNoListen) CreateThread(ThreadGetMyExternalIP, NULL);
{
CreateThread(ThreadGetMyExternalIP, NULL);
}
} }
void StartNode(void* parg) void StartNode(void* parg)
{ {
#ifdef USE_UPNP
#if USE_UPNP
fUseUPnP = GetBoolArg("-upnp", true);
#else
fUseUPnP = GetBoolArg("-upnp", false);
#endif
#endif
if (semOutbound == NULL) { if (semOutbound == NULL) {
// initialize semaphore // initialize semaphore
int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125)); int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
@ -1873,8 +1855,8 @@ void StartNode(void* parg)
printf("Error: CreateThread(ThreadDNSAddressSeed) failed\n"); printf("Error: CreateThread(ThreadDNSAddressSeed) failed\n");
// Map ports with UPnP // Map ports with UPnP
if (fHaveUPnP) if (fUseUPnP)
MapPort(fUseUPnP); MapPort();
// Get addresses from IRC and advertise ours // Get addresses from IRC and advertise ours
if (!CreateThread(ThreadIRCSeed, NULL)) if (!CreateThread(ThreadIRCSeed, NULL))
@ -1930,7 +1912,9 @@ bool StopNode()
if (vnThreadsRunning[THREAD_MINER] > 0) printf("ThreadBitcoinMiner still running\n"); if (vnThreadsRunning[THREAD_MINER] > 0) printf("ThreadBitcoinMiner still running\n");
if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n"); if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n"); if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
if (fHaveUPnP && vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n"); #ifdef USE_UPNP
if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
#endif
if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n"); if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n"); if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n"); if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");

View File

@ -36,7 +36,7 @@ void AddressCurrentlyConnected(const CService& addr);
CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CNetAddr& ip);
CNode* FindNode(const CService& ip); CNode* FindNode(const CService& ip);
CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL, int64 nTimeout=0); CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL, int64 nTimeout=0);
void MapPort(bool fMapPort); void MapPort();
unsigned short GetListenPort(); unsigned short GetListenPort();
bool BindListenPort(const CService &bindAddr, std::string& strError=REF(std::string())); bool BindListenPort(const CService &bindAddr, std::string& strError=REF(std::string()));
void StartNode(void* parg); void StartNode(void* parg);
@ -110,6 +110,8 @@ enum threadId
}; };
extern bool fClient; extern bool fClient;
extern bool fDiscover;
extern bool fUseUPnP;
extern uint64 nLocalServices; extern uint64 nLocalServices;
extern uint64 nLocalHostNonce; extern uint64 nLocalHostNonce;
extern boost::array<int, THREAD_MAX> vnThreadsRunning; extern boost::array<int, THREAD_MAX> vnThreadsRunning;

View File

@ -16,14 +16,11 @@
using namespace std; using namespace std;
// Settings // Settings
int nSocksVersion = 5; typedef std::pair<CService, int> proxyType;
int fUseProxy = false; static proxyType proxyInfo[NET_MAX];
bool fProxyNameLookup = false; static proxyType nameproxyInfo;
bool fNameLookup = false;
CService addrProxy("127.0.0.1",9050);
int nConnectTimeout = 5000; int nConnectTimeout = 5000;
static bool vfNoProxy[NET_MAX] = {}; bool fNameLookup = false;
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
@ -36,11 +33,6 @@ enum Network ParseNetwork(std::string net) {
return NET_UNROUTABLE; return NET_UNROUTABLE;
} }
void SetNoProxy(enum Network net, bool fNoProxy) {
assert(net >= 0 && net < NET_MAX);
vfNoProxy[net] = fNoProxy;
}
bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup) bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
{ {
vIP.clear(); vIP.clear();
@ -431,29 +423,71 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
return true; return true;
} }
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion) {
assert(net >= 0 && net < NET_MAX);
if (nSocksVersion != 0 && nSocksVersion != 4 && nSocksVersion != 5)
return false;
if (nSocksVersion != 0 && !addrProxy.IsValid())
return false;
proxyInfo[net] = std::make_pair(addrProxy, nSocksVersion);
return true;
}
bool GetProxy(enum Network net, CService &addrProxy) {
assert(net >= 0 && net < NET_MAX);
if (!proxyInfo[net].second)
return false;
addrProxy = proxyInfo[net].first;
return true;
}
bool SetNameProxy(CService addrProxy, int nSocksVersion) {
if (nSocksVersion != 0 && nSocksVersion != 5)
return false;
if (nSocksVersion != 0 && !addrProxy.IsValid())
return false;
nameproxyInfo = std::make_pair(addrProxy, nSocksVersion);
return true;
}
bool GetNameProxy() {
return nameproxyInfo.second != 0;
}
bool IsProxy(const CNetAddr &addr) {
for (int i=0; i<NET_MAX; i++) {
if (proxyInfo[i].second && (addr == (CNetAddr)proxyInfo[i].first))
return true;
}
return false;
}
bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout) bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
{ {
const proxyType &proxy = proxyInfo[addrDest.GetNetwork()];
// no proxy needed
if (!proxy.second)
return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout);
SOCKET hSocket = INVALID_SOCKET; SOCKET hSocket = INVALID_SOCKET;
bool fProxy = (fUseProxy && addrDest.IsRoutable() && !vfNoProxy[addrDest.GetNetwork()]);
if (!ConnectSocketDirectly(fProxy ? addrProxy : addrDest, hSocket, nTimeout)) // first connect to proxy server
if (!ConnectSocketDirectly(proxy.first, hSocket, nTimeout))
return false;
// do socks negotiation
switch (proxy.second) {
case 4:
if (!Socks4(addrDest, hSocket))
return false;
break;
case 5:
if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket))
return false;
break;
default:
return false; return false;
if (fProxy)
{
switch(nSocksVersion)
{
case 4:
if (!Socks4(addrDest, hSocket))
return false;
break;
case 5:
default:
if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket))
return false;
break;
}
} }
hSocketRet = hSocket; hSocketRet = hSocket;
@ -465,6 +499,7 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
string strDest(pszDest); string strDest(pszDest);
int port = portDefault; int port = portDefault;
// split hostname and port
size_t colon = strDest.find_last_of(':'); size_t colon = strDest.find_last_of(':');
if (colon != strDest.npos) { if (colon != strDest.npos) {
char *endp = NULL; char *endp = NULL;
@ -479,26 +514,26 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
strDest = strDest.substr(1, strDest.size()-2); strDest = strDest.substr(1, strDest.size()-2);
SOCKET hSocket = INVALID_SOCKET; SOCKET hSocket = INVALID_SOCKET;
CService addrResolved(CNetAddr(strDest, fNameLookup && !fProxyNameLookup), port); CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxyInfo.second), port);
if (addrResolved.IsValid()) { if (addrResolved.IsValid()) {
addr = addrResolved; addr = addrResolved;
return ConnectSocket(addr, hSocketRet, nTimeout); return ConnectSocket(addr, hSocketRet, nTimeout);
} }
addr = CService("0.0.0.0:0"); addr = CService("0.0.0.0:0");
if (!fNameLookup) if (!nameproxyInfo.second)
return false; return false;
if (!ConnectSocketDirectly(addrProxy, hSocket, nTimeout)) if (!ConnectSocketDirectly(nameproxyInfo.first, hSocket, nTimeout))
return false; return false;
switch(nSocksVersion) switch(nameproxyInfo.second)
{ {
case 4: return false; default:
case 5: case 4: return false;
default: case 5:
if (!Socks5(strDest, port, hSocket)) if (!Socks5(strDest, port, hSocket))
return false; return false;
break; break;
} }
hSocketRet = hSocket; hSocketRet = hSocket;
return true; return true;

View File

@ -28,8 +28,8 @@ enum Network
NET_MAX NET_MAX
}; };
enum Network ParseNetwork(std::string net); extern int nConnectTimeout;
void SetNoProxy(enum Network net, bool fNoProxy = true); extern bool fNameLookup;
/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */ /** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */
class CNetAddr class CNetAddr
@ -132,6 +132,12 @@ class CService : public CNetAddr
) )
}; };
enum Network ParseNetwork(std::string net);
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion = 5);
bool GetProxy(enum Network net, CService &addrProxy);
bool IsProxy(const CNetAddr &addr);
bool SetNameProxy(CService addrProxy, int nSocksVersion = 5);
bool GetNameProxy();
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true); 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 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); bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);
@ -140,11 +146,4 @@ bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout); bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout);
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault = 0, int nTimeout = nConnectTimeout); bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault = 0, int nTimeout = nConnectTimeout);
// Settings
extern int nSocksVersion;
extern int fUseProxy;
extern bool fProxyNameLookup;
extern bool fNameLookup;
extern CService addrProxy;
#endif #endif

View File

@ -390,7 +390,7 @@ void NetworkOptionsPage::setMapper(MonitoredDataMapper *mapper)
{ {
// Map model to widgets // Map model to widgets
mapper->addMapping(map_port_upnp, OptionsModel::MapPortUPnP); mapper->addMapping(map_port_upnp, OptionsModel::MapPortUPnP);
mapper->addMapping(connect_socks4, OptionsModel::ConnectSOCKS4); mapper->addMapping(connect_socks4, OptionsModel::ProxyUse);
mapper->addMapping(proxy_ip, OptionsModel::ProxyIP); mapper->addMapping(proxy_ip, OptionsModel::ProxyIP);
mapper->addMapping(proxy_port, OptionsModel::ProxyPort); mapper->addMapping(proxy_port, OptionsModel::ProxyPort);
} }

View File

@ -12,6 +12,29 @@ OptionsModel::OptionsModel(QObject *parent) :
Init(); Init();
} }
bool static ApplyProxySettings()
{
QSettings settings;
CService addrProxy(settings.value("addrProxy", "127.0.0.1:9050").toString().toStdString());
int nSocksVersion(settings.value("nSocksVersion", 5).toInt());
if (!settings.value("fUseProxy", false).toBool()) {
addrProxy = CService();
nSocksVersion = 0;
}
if (nSocksVersion && !addrProxy.IsValid())
return false;
if (!IsLimited(NET_IPV4))
SetProxy(NET_IPV4, addrProxy, nSocksVersion);
if (nSocksVersion > 4) {
#ifdef USE_IPV6
if (!IsLimited(NET_IPV6))
SetProxy(NET_IPV6, addrProxy, nSocksVersion);
#endif
SetNameProxy(addrProxy, nSocksVersion);
}
return true;
}
void OptionsModel::Init() void OptionsModel::Init()
{ {
QSettings settings; QSettings settings;
@ -75,20 +98,21 @@ bool OptionsModel::Upgrade()
CAddress addrProxyAddress; CAddress addrProxyAddress;
if (walletdb.ReadSetting("addrProxy", addrProxyAddress)) if (walletdb.ReadSetting("addrProxy", addrProxyAddress))
{ {
addrProxy = addrProxyAddress; settings.setValue("addrProxy", addrProxyAddress.ToStringIPPort().c_str());
settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str());
walletdb.EraseSetting("addrProxy"); walletdb.EraseSetting("addrProxy");
} }
} }
catch (std::ios_base::failure &e) catch (std::ios_base::failure &e)
{ {
// 0.6.0rc1 saved this as a CService, which causes failure when parsing as a CAddress // 0.6.0rc1 saved this as a CService, which causes failure when parsing as a CAddress
CService addrProxy;
if (walletdb.ReadSetting("addrProxy", addrProxy)) if (walletdb.ReadSetting("addrProxy", addrProxy))
{ {
settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str()); settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str());
walletdb.EraseSetting("addrProxy"); walletdb.EraseSetting("addrProxy");
} }
} }
ApplyProxySettings();
Init(); Init();
return true; return true;
@ -115,12 +139,24 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
return settings.value("fUseUPnP", GetBoolArg("-upnp", true)); return settings.value("fUseUPnP", GetBoolArg("-upnp", true));
case MinimizeOnClose: case MinimizeOnClose:
return QVariant(fMinimizeOnClose); return QVariant(fMinimizeOnClose);
case ConnectSOCKS4: case ProxyUse:
return settings.value("fUseProxy", false); return settings.value("fUseProxy", false);
case ProxyIP: case ProxySocksVersion:
return QVariant(QString::fromStdString(addrProxy.ToStringIP())); return settings.value("nSocksVersion", false);
case ProxyPort: case ProxyIP: {
return QVariant(addrProxy.GetPort()); CService addrProxy;
if (GetProxy(NET_IPV4, addrProxy))
return QVariant(QString::fromStdString(addrProxy.ToStringIP()));
else
return QVariant(QString::fromStdString("localhost"));
}
case ProxyPort: {
CService addrProxy;
if (GetProxy(NET_IPV4, addrProxy))
return QVariant(addrProxy.GetPort());
else
return 9050;
}
case Fee: case Fee:
return QVariant(nTransactionFee); return QVariant(nTransactionFee);
case DisplayUnit: case DisplayUnit:
@ -137,7 +173,6 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
} }
return QVariant(); return QVariant();
} }
bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, int role) bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, int role)
{ {
bool successful = true; /* set to false on parse error */ bool successful = true; /* set to false on parse error */
@ -155,27 +190,29 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
break; break;
case MapPortUPnP: case MapPortUPnP:
{ {
bool bUseUPnP = value.toBool(); fUseUPnP = value.toBool();
settings.setValue("fUseUPnP", bUseUPnP); settings.setValue("fUseUPnP", fUseUPnP);
MapPort(bUseUPnP); MapPort();
} }
break; break;
case MinimizeOnClose: case MinimizeOnClose:
fMinimizeOnClose = value.toBool(); fMinimizeOnClose = value.toBool();
settings.setValue("fMinimizeOnClose", fMinimizeOnClose); settings.setValue("fMinimizeOnClose", fMinimizeOnClose);
break; break;
case ConnectSOCKS4: case ProxyUse:
fUseProxy = value.toBool(); settings.setValue("fUseProxy", value.toBool());
settings.setValue("fUseProxy", fUseProxy); ApplyProxySettings();
break; break;
case ProxyIP: case ProxyIP:
{ {
// Use CAddress to parse and check IP CService addrProxy("127.0.0.1", 9050);
GetProxy(NET_IPV4, addrProxy);
CNetAddr addr(value.toString().toStdString()); CNetAddr addr(value.toString().toStdString());
if (addr.IsValid()) if (addr.IsValid())
{ {
addrProxy.SetIP(addr); addrProxy.SetIP(addr);
settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str()); settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str());
successful = ApplyProxySettings();
} }
else else
{ {
@ -185,11 +222,14 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
break; break;
case ProxyPort: case ProxyPort:
{ {
CService addrProxy("127.0.0.1", 9050);
GetProxy(NET_IPV4, addrProxy);
int nPort = atoi(value.toString().toAscii().data()); int nPort = atoi(value.toString().toAscii().data());
if (nPort > 0 && nPort < std::numeric_limits<unsigned short>::max()) if (nPort > 0 && nPort < std::numeric_limits<unsigned short>::max())
{ {
addrProxy.SetPort(nPort); addrProxy.SetPort(nPort);
settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str()); settings.setValue("addrProxy", addrProxy.ToStringIPPort().c_str());
successful = ApplyProxySettings();
} }
else else
{ {

View File

@ -20,7 +20,8 @@ public:
MinimizeToTray, // bool MinimizeToTray, // bool
MapPortUPnP, // bool MapPortUPnP, // bool
MinimizeOnClose, // bool MinimizeOnClose, // bool
ConnectSOCKS4, // bool ProxyUse, // bool
ProxySocksVersion, // int
ProxyIP, // QString ProxyIP, // QString
ProxyPort, // QString ProxyPort, // QString
Fee, // qint64 Fee, // qint64