Guest User

4diff-0.6.0

a guest
Apr 27th, 2012
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 32.45 KB | None | 0 0
  1. diff -Nurp src.old/bitcoinrpc.cpp src/bitcoinrpc.cpp
  2. --- src.old/bitcoinrpc.cpp 2012-04-25 00:42:11.482004955 -0700
  3. +++ src/bitcoinrpc.cpp 2012-04-26 18:04:42.161964416 -0700
  4. @@ -3,6 +3,16 @@
  5. // Distributed under the MIT/X11 software license, see the accompanying
  6. // file license.txt or http://www.opensource.org/licenses/mit-license.php.
  7.  
  8. +// CAUTION: This is not the offical bitcoinrpc.cpp from the official
  9. +// bitcoin distribution. It has been modified by me
  10. +// <davidjoelschwartz@gmail.com> to support multi-threaded RPC.
  11. +// This is quick and dirty code, it may not work for you. No warranties
  12. +// are expressed or implied. I made a best effort to improve the RPC
  13. +// performance. This notification is for blame, not for credit and
  14. +// may be removed if this change, or one similar, is accepted into the
  15. +// main distribution. If this has helped you, please donate to:
  16. +// 1H3STBxuzEHZQQD4hkjVE22TWTazcZzeBw
  17. +
  18. #include "main.h"
  19. #include "wallet.h"
  20. #include "db.h"
  21. @@ -12,6 +22,8 @@
  22. #include "ui_interface.h"
  23. #include "bitcoinrpc.h"
  24.  
  25. +#define BOOST_SPIRIT_THREADSAFE
  26. +
  27. #undef printf
  28. #include <boost/asio.hpp>
  29. #include <boost/filesystem.hpp>
  30. @@ -44,6 +56,8 @@ static CCriticalSection cs_nWalletUnlock
  31. extern Value dumpprivkey(const Array& params, bool fHelp);
  32. extern Value importprivkey(const Array& params, bool fHelp);
  33.  
  34. +void ThreadRPCServer3(void* parg);
  35. +
  36. Object JSONRPCError(int code, const string& message)
  37. {
  38. Object error;
  39. @@ -229,6 +243,15 @@ Value stop(const Array& params, bool fHe
  40. return "bitcoin server stopping";
  41. }
  42.  
  43. +Value sendpollpidsignal(const Array& params, bool fHelp)
  44. +{
  45. + if (fHelp)
  46. + throw runtime_error(
  47. + "sendpollpidsignal\n"
  48. + "Returns number of successful signals sent to polling pids.");
  49. +
  50. + return SendPollPidSignal(SIGUSR1);
  51. +}
  52.  
  53. Value getblockcount(const Array& params, bool fHelp)
  54. {
  55. @@ -2052,6 +2075,7 @@ static const CRPCCommand vRPCCommands[]
  56. { "getwork", &getwork, true },
  57. { "listaccounts", &listaccounts, false },
  58. { "settxfee", &settxfee, false },
  59. + { "sendpollpidsignal", &sendpollpidsignal, false },
  60. { "getmemorypool", &getmemorypool, true },
  61. { "listsinceblock", &listsinceblock, false },
  62. { "dumpprivkey", &dumpprivkey, false },
  63. @@ -2115,7 +2139,7 @@ string rfc1123Time()
  64. return string(buffer);
  65. }
  66.  
  67. -static string HTTPReply(int nStatus, const string& strMsg)
  68. +static string HTTPReply(int nStatus, const string& strMsg, bool keepalive)
  69. {
  70. if (nStatus == 401)
  71. return strprintf("HTTP/1.0 401 Authorization Required\r\n"
  72. @@ -2144,7 +2168,7 @@ static string HTTPReply(int nStatus, con
  73. return strprintf(
  74. "HTTP/1.1 %d %s\r\n"
  75. "Date: %s\r\n"
  76. - "Connection: close\r\n"
  77. + "Connection: %s\r\n"
  78. "Content-Length: %d\r\n"
  79. "Content-Type: application/json\r\n"
  80. "Server: bitcoin-json-rpc/%s\r\n"
  81. @@ -2153,12 +2177,13 @@ static string HTTPReply(int nStatus, con
  82. nStatus,
  83. cStatus,
  84. rfc1123Time().c_str(),
  85. + keepalive ? "keep-alive" : "close",
  86. strMsg.size(),
  87. FormatFullVersion().c_str(),
  88. strMsg.c_str());
  89. }
  90.  
  91. -int ReadHTTPStatus(std::basic_istream<char>& stream)
  92. +int ReadHTTPStatus(std::basic_istream<char>& stream, int &proto)
  93. {
  94. string str;
  95. getline(stream, str);
  96. @@ -2166,6 +2191,10 @@ int ReadHTTPStatus(std::basic_istream<ch
  97. boost::split(vWords, str, boost::is_any_of(" "));
  98. if (vWords.size() < 2)
  99. return 500;
  100. + proto = 0;
  101. + const char *ver = strstr(str.c_str(), "HTTP/1.");
  102. + if (ver != NULL)
  103. + proto = atoi(ver+7);
  104. return atoi(vWords[1].c_str());
  105. }
  106.  
  107. @@ -2200,7 +2229,8 @@ int ReadHTTP(std::basic_istream<char>& s
  108. strMessageRet = "";
  109.  
  110. // Read status
  111. - int nStatus = ReadHTTPStatus(stream);
  112. + int nProto;
  113. + int nStatus = ReadHTTPStatus(stream, nProto);
  114.  
  115. // Read header
  116. int nLen = ReadHTTPHeader(stream, mapHeadersRet);
  117. @@ -2215,6 +2245,16 @@ int ReadHTTP(std::basic_istream<char>& s
  118. strMessageRet = string(vch.begin(), vch.end());
  119. }
  120.  
  121. + string sConHdr=mapHeadersRet["connection"];
  122. +
  123. + if ( (sConHdr != "close") && (sConHdr != "keep-alive") )
  124. + {
  125. + if(nProto >= 1)
  126. + mapHeadersRet["connection"]="keep-alive";
  127. + else
  128. + mapHeadersRet["connection"]="close";
  129. + }
  130. +
  131. return nStatus;
  132. }
  133.  
  134. @@ -2267,7 +2307,7 @@ void ErrorReply(std::ostream& stream, co
  135. if (code == -32600) nStatus = 400;
  136. else if (code == -32601) nStatus = 404;
  137. string strReply = JSONRPCReply(Value::null, objError, id);
  138. - stream << HTTPReply(nStatus, strReply) << std::flush;
  139. + stream << HTTPReply(nStatus, strReply, false) << std::flush;
  140. }
  141.  
  142. bool ClientAllowed(const string& strAddress)
  143. @@ -2333,6 +2373,20 @@ private:
  144. SSLStream& stream;
  145. };
  146.  
  147. +class AcceptedConnection
  148. +{
  149. + public:
  150. + SSLStream sslStream;
  151. + SSLIOStreamDevice d;
  152. + iostreams::stream<SSLIOStreamDevice> stream;
  153. +
  154. + ip::tcp::endpoint peer;
  155. +
  156. + AcceptedConnection(asio::io_service &io_service, ssl::context &context,
  157. + bool fUseSSL) : sslStream(io_service, context), d(sslStream, fUseSSL),
  158. + stream(d) { ; }
  159. +};
  160. +
  161. void ThreadRPCServer(void* parg)
  162. {
  163. IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
  164. @@ -2356,8 +2410,8 @@ void ThreadRPCServer2(void* parg)
  165. {
  166. printf("ThreadRPCServer started\n");
  167.  
  168. - strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
  169. - if (mapArgs["-rpcpassword"] == "")
  170. + strRPCUserColonPass = strRPCUser + ":" + strRPCPass;
  171. + if (strRPCPass == "")
  172. {
  173. unsigned char rand_pwd[32];
  174. RAND_bytes(rand_pwd, 32);
  175. @@ -2424,55 +2478,74 @@ void ThreadRPCServer2(void* parg)
  176. loop
  177. {
  178. // Accept connection
  179. - SSLStream sslStream(io_service, context);
  180. - SSLIOStreamDevice d(sslStream, fUseSSL);
  181. - iostreams::stream<SSLIOStreamDevice> stream(d);
  182. + AcceptedConnection *conn=new AcceptedConnection(io_service, context, fUseSSL);
  183.  
  184. ip::tcp::endpoint peer;
  185. vnThreadsRunning[THREAD_RPCSERVER]--;
  186. - acceptor.accept(sslStream.lowest_layer(), peer);
  187. - vnThreadsRunning[4]++;
  188. + acceptor.accept(conn->sslStream.lowest_layer(), conn->peer);
  189. + vnThreadsRunning[THREAD_RPCSERVER]++;
  190. if (fShutdown)
  191. + {
  192. + delete conn;
  193. return;
  194. + }
  195.  
  196. // Restrict callers by IP
  197. - if (!ClientAllowed(peer.address().to_string()))
  198. + if (!ClientAllowed(conn->peer.address().to_string()))
  199. {
  200. // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
  201. if (!fUseSSL)
  202. - stream << HTTPReply(403, "") << std::flush;
  203. - continue;
  204. + conn->stream << HTTPReply(403, "", false) << std::flush;
  205. + delete conn;
  206. + }
  207. + else
  208. + CreateThread(ThreadRPCServer3, (void *) conn);
  209. + }
  210. +}
  211. +
  212. +void ThreadRPCServer3(void* parg)
  213. +{
  214. + IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer3(parg));
  215. + vnThreadsRunning[THREAD_RPCSERVER0]++;
  216. + AcceptedConnection *conn=(AcceptedConnection *) parg;
  217. +
  218. + bool fRun = true;
  219. + loop
  220. + {
  221. + if (fShutdown || !fRun)
  222. + {
  223. + conn->stream.close();
  224. + delete conn;
  225. + vnThreadsRunning[THREAD_RPCSERVER0]--;
  226. + return;
  227. }
  228.  
  229. map<string, string> mapHeaders;
  230. string strRequest;
  231.  
  232. - boost::thread api_caller(ReadHTTP, boost::ref(stream), boost::ref(mapHeaders), boost::ref(strRequest));
  233. - if (!api_caller.timed_join(boost::posix_time::seconds(GetArg("-rpctimeout", 30))))
  234. - { // Timed out:
  235. - acceptor.cancel();
  236. - printf("ThreadRPCServer ReadHTTP timeout\n");
  237. - continue;
  238. - }
  239. + ReadHTTP(conn->stream, mapHeaders, strRequest);
  240.  
  241. // Check authorization
  242. if (mapHeaders.count("authorization") == 0)
  243. {
  244. - stream << HTTPReply(401, "") << std::flush;
  245. - continue;
  246. + conn->stream << HTTPReply(401, "", false) << std::flush;
  247. + break;
  248. }
  249. if (!HTTPAuthorized(mapHeaders))
  250. {
  251. - printf("ThreadRPCServer incorrect password attempt from %s\n",peer.address().to_string().c_str());
  252. + printf("ThreadRPCServer incorrect password attempt from %s\n",conn->peer.address().to_string().c_str());
  253. /* Deter brute-forcing short passwords.
  254. If this results in a DOS the user really
  255. shouldn't have their RPC port exposed.*/
  256. if (mapArgs["-rpcpassword"].size() < 20)
  257. Sleep(250);
  258.  
  259. - stream << HTTPReply(401, "") << std::flush;
  260. - continue;
  261. + conn->stream << HTTPReply(401, "", false) << std::flush;
  262. + break;
  263. }
  264. + if (mapHeaders["connection"] == "close")
  265. + fRun = false;
  266. +
  267.  
  268. Value id = Value::null;
  269. try
  270. @@ -2528,22 +2601,32 @@ void ThreadRPCServer2(void* parg)
  271.  
  272. // Send reply
  273. string strReply = JSONRPCReply(result, Value::null, id);
  274. - stream << HTTPReply(200, strReply) << std::flush;
  275. + conn->stream << HTTPReply(200, strReply, fRun) << std::flush;
  276. }
  277. catch (std::exception& e)
  278. {
  279. - ErrorReply(stream, JSONRPCError(-1, e.what()), id);
  280. + ErrorReply(conn->stream, JSONRPCError(-1, e.what()), id);
  281. + fRun = false;
  282. + }
  283. + catch (Object& e)
  284. + {
  285. + ErrorReply(conn->stream, e, id);
  286. + fRun = false;
  287. }
  288. }
  289. catch (Object& objError)
  290. {
  291. - ErrorReply(stream, objError, id);
  292. + ErrorReply(conn->stream, objError, id);
  293. + break;
  294. }
  295. catch (std::exception& e)
  296. {
  297. - ErrorReply(stream, JSONRPCError(-32700, e.what()), id);
  298. + ErrorReply(conn->stream, JSONRPCError(-32700, e.what()), id);
  299. + break;
  300. }
  301. }
  302. + delete conn;
  303. + vnThreadsRunning[THREAD_RPCSERVER0]--;
  304. }
  305.  
  306.  
  307. @@ -2551,7 +2634,7 @@ void ThreadRPCServer2(void* parg)
  308.  
  309. Object CallRPC(const string& strMethod, const Array& params)
  310. {
  311. - if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
  312. + if (strRPCUser == "" && strRPCPass == "")
  313. throw runtime_error(strprintf(
  314. _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
  315. "If the file does not exist, create it with owner-readable-only file permissions."),
  316. @@ -2569,7 +2652,7 @@ Object CallRPC(const string& strMethod,
  317. throw runtime_error("couldn't connect to server");
  318.  
  319. // HTTP basic authentication
  320. - string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
  321. + string strUserPass64 = EncodeBase64(strRPCUser + ":" + strRPCPass);
  322. map<string, string> mapRequestHeaders;
  323. mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
  324.  
  325. diff -Nurp src.old/build.h src/build.h
  326. --- src.old/build.h 1969-12-31 16:00:00.000000000 -0800
  327. +++ src/build.h 2012-04-26 18:04:42.161964416 -0700
  328. @@ -0,0 +1,2 @@
  329. +#define BUILD_DESC "v0.6.0-194-gc2e8c8a-dirty"
  330. +#define BUILD_DATE "2012-04-23 21:33:29 -0700"
  331. diff -Nurp src.old/init.cpp src/init.cpp
  332. --- src.old/init.cpp 2012-04-25 00:42:11.482004955 -0700
  333. +++ src/init.cpp 2012-04-26 18:04:42.161964416 -0700
  334. @@ -194,6 +194,7 @@ bool AppInit2(int argc, char* argv[])
  335. " -bantime=<n> \t " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" +
  336. " -maxreceivebuffer=<n>\t " + _("Maximum per-connection receive buffer, <n>*1000 bytes (default: 10000)") + "\n" +
  337. " -maxsendbuffer=<n>\t " + _("Maximum per-connection send buffer, <n>*1000 bytes (default: 10000)") + "\n" +
  338. + " -hub=<n> \t " + _("Enable hub mode (1-4)\n") +
  339. #ifdef USE_UPNP
  340. #if USE_UPNP
  341. " -upnp \t " + _("Use Universal Plug and Play to map the listening port (default: 1)") + "\n" +
  342. @@ -220,6 +221,7 @@ bool AppInit2(int argc, char* argv[])
  343. " -rpcport=<port> \t\t " + _("Listen for JSON-RPC connections on <port> (default: 8332)") + "\n" +
  344. " -rpcallowip=<ip> \t\t " + _("Allow JSON-RPC connections from specified IP address") + "\n" +
  345. " -rpcconnect=<ip> \t " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n" +
  346. + " -pollpidfile=<f> \t " + _("Support long polling\n") +
  347. " -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n" +
  348. " -upgradewallet \t " + _("Upgrade wallet to latest format") + "\n" +
  349. " -keypool=<n> \t " + _("Set key pool size to <n> (default: 100)") + "\n" +
  350. @@ -267,6 +269,9 @@ bool AppInit2(int argc, char* argv[])
  351. else
  352. fServer = GetBoolArg("-server");
  353.  
  354. + strRPCUser = mapArgs["-rpcuser"];
  355. + strRPCPass = mapArgs["-rpcpassword"];
  356. +
  357. /* force fServer when running without GUI */
  358. #if !defined(QT_GUI)
  359. fServer = true;
  360. diff -Nurp src.old/main.cpp src/main.cpp
  361. --- src.old/main.cpp 2012-04-25 00:42:11.482004955 -0700
  362. +++ src/main.cpp 2012-04-26 18:04:42.161964416 -0700
  363. @@ -10,6 +10,7 @@
  364. #include <boost/algorithm/string/replace.hpp>
  365. #include <boost/filesystem.hpp>
  366. #include <boost/filesystem/fstream.hpp>
  367. +#include <signal.h>
  368.  
  369. using namespace std;
  370. using namespace boost;
  371. @@ -1488,6 +1489,7 @@ bool CBlock::SetBestChainInner(CTxDB& tx
  372. bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
  373. {
  374. uint256 hash = GetHash();
  375. + bool lp = false;
  376.  
  377. txdb.TxnBegin();
  378. if (pindexGenesisBlock == NULL && hash == hashGenesisBlock)
  379. @@ -1549,6 +1551,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, C
  380. bool fIsInitialDownload = IsInitialBlockDownload();
  381. if (!fIsInitialDownload)
  382. {
  383. + lp = true;
  384. const CBlockLocator locator(pindexNew);
  385. ::SetBestChain(locator);
  386. }
  387. @@ -1562,6 +1565,12 @@ bool CBlock::SetBestChain(CTxDB& txdb, C
  388. nTransactionsUpdated++;
  389. printf("SetBestChain: new best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());
  390.  
  391. + if(lp)
  392. + {
  393. + // Support long polling
  394. + SendPollPidSignal(SIGUSR1);
  395. + }
  396. +
  397. std::string strCmd = GetArg("-blocknotify", "");
  398.  
  399. if (!fIsInitialDownload && !strCmd.empty())
  400. @@ -2019,6 +2028,31 @@ void PrintBlockTree()
  401. }
  402.  
  403.  
  404. +int SendPollPidSignal(int signal)
  405. +{
  406. + string lp_pid;
  407. + char s[64];
  408. + int ret = 0;
  409. +
  410. + strcpy(s, "-pollpidfile");
  411. + for(int i=1; i<=2; ++i) {
  412. + if(i>1) snprintf(s+12, sizeof(s)-12, "%u", i);
  413. +
  414. + lp_pid = mapArgs[s];
  415. + if(lp_pid != "")
  416. + {
  417. + FILE *pidFile = fopen(lp_pid.c_str(), "r");
  418. + if(pidFile!=NULL)
  419. + {
  420. + int pid=0;
  421. + if ((fscanf(pidFile, "%d", &pid) == 1) && (pid > 1))
  422. + if(-1!=kill((pid_t) pid, signal)) ++ret;
  423. + fclose(pidFile);
  424. + }
  425. + }
  426. + }
  427. + return ret;
  428. +}
  429.  
  430.  
  431.  
  432. @@ -3503,7 +3537,7 @@ void static BitcoinMiner(CWallet *pwalle
  433. {
  434. nLogTime = GetTime();
  435. printf("%s ", DateTimeStrFormat("%x %H:%M", GetTime()).c_str());
  436. - printf("hashmeter %3d CPUs %6.0f khash/s\n", vnThreadsRunning[THREAD_MINER], dHashesPerSec/1000.0);
  437. + printf("hashmeter %3d CPUs %6.0f khash/s\n", (long)vnThreadsRunning[THREAD_MINER], dHashesPerSec/1000.0);
  438. }
  439. }
  440. }
  441. @@ -3557,7 +3591,7 @@ void static ThreadBitcoinMiner(void* par
  442. nHPSTimerStart = 0;
  443. if (vnThreadsRunning[THREAD_MINER] == 0)
  444. dHashesPerSec = 0;
  445. - printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINER]);
  446. + printf("ThreadBitcoinMiner exiting, %d threads remaining\n", (long)vnThreadsRunning[THREAD_MINER]);
  447. }
  448.  
  449.  
  450. diff -Nurp src.old/main.h src/main.h
  451. --- src.old/main.h 2012-04-25 00:42:11.482004955 -0700
  452. +++ src/main.h 2012-04-26 18:04:42.161964416 -0700
  453. @@ -101,6 +101,7 @@ unsigned int ComputeMinWork(unsigned int
  454. int GetNumBlocksOfPeers();
  455. bool IsInitialBlockDownload();
  456. std::string GetWarnings(std::string strFor);
  457. +int SendPollPidSignal(int signal);
  458.  
  459.  
  460.  
  461. diff -Nurp src.old/makefile.unix src/makefile.unix
  462. --- src.old/makefile.unix 2012-04-26 18:06:01.083216416 -0700
  463. +++ src/makefile.unix 2012-04-26 18:05:33.193216600 -0700
  464. @@ -2,7 +2,7 @@
  465. # Distributed under the MIT/X11 software license, see the accompanying
  466. # file license.txt or http://www.opensource.org/licenses/mit-license.php.
  467.  
  468. -USE_UPNP:=0
  469. +#USE_UPNP:=0
  470.  
  471. DEFS=-DNOPCH
  472.  
  473. diff -Nurp src.old/netbase.cpp src/netbase.cpp
  474. --- src.old/netbase.cpp 2012-04-25 00:42:11.482004955 -0700
  475. +++ src/netbase.cpp 2012-04-26 18:04:42.161964416 -0700
  476. @@ -521,7 +521,7 @@ std::vector<unsigned char> CNetAddr::Get
  477. std::vector<unsigned char> vchRet;
  478. int nClass = 0; // 0=IPv6, 1=IPv4, 254=local, 255=unroutable
  479. int nStartByte = 0;
  480. - int nBits = 16;
  481. + int nBits = HubModes[nHubMode][HM_IP4_BITS];
  482.  
  483. // all local addresses belong to the same group
  484. if (IsLocal())
  485. @@ -559,10 +559,10 @@ std::vector<unsigned char> CNetAddr::Get
  486. }
  487. // for he.net, use /36 groups
  488. else if (GetByte(15) == 0x20 && GetByte(14) == 0x11 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
  489. - nBits = 36;
  490. + nBits = HubModes[nHubMode][HM_IP6_BITS]+4;
  491. // for the rest of the IPv6 network, use /32 groups
  492. else
  493. - nBits = 32;
  494. + nBits = HubModes[nHubMode][HM_IP6_BITS];
  495.  
  496. vchRet.push_back(nClass);
  497. while (nBits >= 8)
  498. diff -Nurp src.old/netbase.h src/netbase.h
  499. --- src.old/netbase.h 2012-04-25 00:42:11.482004955 -0700
  500. +++ src/netbase.h 2012-04-26 18:04:42.161964416 -0700
  501. @@ -17,6 +17,16 @@ extern int nConnectTimeout;
  502. #undef SetPort
  503. #endif
  504.  
  505. +enum {
  506. + HM_MAX_OUTBOUND=0,
  507. + HM_MAX_TOTAL,
  508. + HM_IP4_BITS,
  509. + HM_IP6_BITS,
  510. + HM_MULTITHREAD,
  511. +};
  512. +extern int nHubMode;
  513. +extern const unsigned HubModes[5][5];
  514. +
  515. /** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */
  516. class CNetAddr
  517. {
  518. diff -Nurp src.old/net.cpp src/net.cpp
  519. --- src.old/net.cpp 2012-04-25 00:42:11.482004955 -0700
  520. +++ src/net.cpp 2012-04-26 18:04:42.161964416 -0700
  521. @@ -22,9 +22,38 @@
  522. #include <miniupnpc/upnperrors.h>
  523. #endif
  524.  
  525. +// CAUTION: This is not the offical net.cpp from the official
  526. +// bitcoin distribution. It has been modified by me
  527. +// <DavidJoelSchwartz@gmail.com> to support 'hub' modes.
  528. +// This is quick and dirty code, it may not work for you. No warranties
  529. +// are expressed or implied. I made a best effort to improve the RPC
  530. +// performance. This notification is for blame, not for credit and
  531. +// may be removed if this change, or one similar, is accepted into the
  532. +// main distribution. If this has helped you, please donate to:
  533. +// 1H3STBxuzEHZQQD4hkjVE22TWTazcZzeBw
  534. +
  535. using namespace std;
  536. using namespace boost;
  537.  
  538. +int nHubMode = 0;
  539. +const unsigned HubModes[5][5]=
  540. +{ // outbound connections, total connections, IP mask, multithreaded connect
  541. + { 8, 125, 16, 32, 0 }, // Normal mode
  542. + { 16, 200, 16, 32, 0 }, // Small hub mode
  543. + { 32, 384, 24, 36, 1 }, // Medium hub mode
  544. + { 32, 640, 24, 36, 1 }, // Large hub mode
  545. + { 32, 1536, 32, 40, 1 } // Largest hub mode
  546. +};
  547. +
  548. +#if defined(FD_SETSIZE) && (FD_SETSIZE<1600)
  549. +#if FD_SETSIZE<1024
  550. +#warning This build will not be able to run at high hub levels
  551. +#else
  552. +#warning This build will not be able to run at hub mode 4
  553. +#endif
  554. +#endif
  555. +
  556. +
  557. static const int MAX_OUTBOUND_CONNECTIONS = 8;
  558.  
  559. void ThreadMessageHandler2(void* parg);
  560. @@ -49,7 +78,7 @@ uint64 nLocalServices = (fClient ? 0 : N
  561. CAddress addrLocalHost(CService("0.0.0.0", 0), nLocalServices);
  562. static CNode* pnodeLocalHost = NULL;
  563. uint64 nLocalHostNonce = 0;
  564. -array<int, THREAD_MAX> vnThreadsRunning;
  565. +array<atomic_long, THREAD_MAX> vnThreadsRunning;
  566. static SOCKET hListenSocket = INVALID_SOCKET;
  567. CAddrMan addrman;
  568.  
  569. @@ -68,6 +97,11 @@ static CWaitableCriticalSection csOutbou
  570. static int nOutbound = 0;
  571. static CConditionVariable condOutbound;
  572.  
  573. +// Work Notification
  574. +boost::mutex mWorkNotification;
  575. +boost::condition_variable cvWorkNotification;
  576. +bool fWorkFound;
  577. +
  578.  
  579. unsigned short GetListenPort()
  580. {
  581. @@ -659,7 +693,7 @@ void ThreadSocketHandler2(void* parg)
  582. if (WSAGetLastError() != WSAEWOULDBLOCK)
  583. printf("socket error accept failed: %d\n", WSAGetLastError());
  584. }
  585. - else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
  586. + else if (nInbound >= GetArg("-maxconnections", HubModes[nHubMode][HM_MAX_TOTAL]) - HubModes[nHubMode][HM_MAX_OUTBOUND])
  587. {
  588. {
  589. LOCK(cs_setservAddNodeAddresses);
  590. @@ -695,10 +729,16 @@ void ThreadSocketHandler2(void* parg)
  591. BOOST_FOREACH(CNode* pnode, vNodesCopy)
  592. pnode->AddRef();
  593. }
  594. + bool fGotData = false;
  595. BOOST_FOREACH(CNode* pnode, vNodesCopy)
  596. {
  597. if (fShutdown)
  598. + {
  599. + LOCK(cs_vNodes);
  600. + BOOST_FOREACH(CNode* pnode, vNodesCopy)
  601. + pnode->Release();
  602. return;
  603. + }
  604.  
  605. //
  606. // Receive
  607. @@ -727,6 +767,8 @@ void ThreadSocketHandler2(void* parg)
  608. vRecv.resize(nPos + nBytes);
  609. memcpy(&vRecv[nPos], pchBuf, nBytes);
  610. pnode->nLastRecv = GetTime();
  611. + pnode->fNeedProcess = true;
  612. + fGotData = true;
  613. }
  614. else if (nBytes == 0)
  615. {
  616. @@ -788,6 +830,14 @@ void ThreadSocketHandler2(void* parg)
  617. }
  618. }
  619.  
  620. + if (fGotData)
  621. + {
  622. + mWorkNotification.lock();
  623. + fWorkFound = true;
  624. + mWorkNotification.unlock();
  625. + cvWorkNotification.notify_one();
  626. + }
  627. +
  628. //
  629. // Inactivity checking
  630. //
  631. @@ -818,7 +868,7 @@ void ThreadSocketHandler2(void* parg)
  632. pnode->Release();
  633. }
  634.  
  635. - Sleep(10);
  636. + Sleep(2);
  637. }
  638. }
  639.  
  640. @@ -1055,6 +1105,16 @@ void ThreadDNSAddressSeed2(void* parg)
  641.  
  642.  
  643.  
  644. +void ONCThread(void *parg)
  645. +{ // Open a network connection in a thread
  646. + IMPLEMENT_RANDOMIZE_STACK(ONCThread(parg));
  647. + CAddress *addr=(CAddress *) parg;
  648. + vnThreadsRunning[THREAD_CONNECT]++;
  649. + OpenNetworkConnection(*addr);
  650. + vnThreadsRunning[THREAD_CONNECT]--;
  651. + delete addr;
  652. +}
  653. +
  654.  
  655. unsigned int pnSeed[] =
  656. {
  657. @@ -1192,6 +1252,31 @@ void ThreadOpenConnections2(void* parg)
  658. {
  659. printf("ThreadOpenConnections started\n");
  660.  
  661. + // Determine and validate configured hub mode
  662. + string sHubMode=GetArg("-hub", "0");
  663. + int nHM=atoi(sHubMode);
  664. + if ((nHM >= 0) && (nHM <= 4))
  665. + nHubMode = nHM;
  666. + if( ( sizeof(fd_set) * 8 ) < ( HubModes[nHubMode][HM_MAX_TOTAL] + 32 ) )
  667. + {
  668. + fShutdown = true;
  669. + printf("*** Unable to support requested hub mode due to compilation flags\n");
  670. + CreateThread(Shutdown, NULL);
  671. + return;
  672. + }
  673. +
  674. +#ifdef RLIMIT_NOFILE
  675. + struct rlimit srLimit;
  676. + if ( (getrlimit(RLIMIT_NOFILE, &srLimit) == 0) &&
  677. + (srLimit.rlim_cur < ( HubModes[nHubMode][HM_MAX_TOTAL] + 32 ) ) )
  678. + {
  679. + fShutdown = true;
  680. + printf("*** Unable to support requested hub mode due to resource limit\n");
  681. + CreateThread(Shutdown, NULL);
  682. + return;
  683. + }
  684. +#endif
  685. +
  686. // Connect to specific addresses
  687. if (mapArgs.count("-connect"))
  688. {
  689. @@ -1216,14 +1301,12 @@ void ThreadOpenConnections2(void* parg)
  690. int64 nStart = GetTime();
  691. loop
  692. {
  693. - vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
  694. - Sleep(500);
  695. - vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
  696. if (fShutdown)
  697. return;
  698.  
  699. // Limit outbound connections
  700. - int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
  701. + int nMaxOutbound = HubModes[nHubMode][HM_MAX_OUTBOUND];
  702. + nMaxOutbound = min(nMaxOutbound, (int)GetArg("-maxconnections", nMaxOutbound));
  703. vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
  704. {
  705. WAITABLE_LOCK(csOutbound);
  706. @@ -1233,9 +1316,11 @@ void ThreadOpenConnections2(void* parg)
  707. if (fShutdown)
  708. return;
  709.  
  710. + int64 nNow = GetTime();
  711. +
  712. // Add seed nodes if IRC isn't working
  713. bool fTOR = (fUseProxy && addrProxy.GetPort() == 9050);
  714. - if (addrman.size()==0 && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
  715. + if (addrman.size()==0 && (nNow - nStart > 60 || fTOR) && !fTestNet)
  716. {
  717. std::vector<CAddress> vAdd;
  718. for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
  719. @@ -1248,7 +1333,7 @@ void ThreadOpenConnections2(void* parg)
  720. struct in_addr ip;
  721. memcpy(&ip, &pnSeed[i], sizeof(ip));
  722. CAddress addr(CService(ip, GetDefaultPort()));
  723. - addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
  724. + addr.nTime = nNow-GetRand(nOneWeek)-nOneWeek;
  725. vAdd.push_back(addr);
  726. }
  727. addrman.Add(vAdd, CNetAddr("127.0.0.1"));
  728. @@ -1259,7 +1344,7 @@ void ThreadOpenConnections2(void* parg)
  729. //
  730. CAddress addrConnect;
  731.  
  732. - // Only connect to one address per a.b.?.? range.
  733. + // Only connect to one address per IP block
  734. // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
  735. set<vector<unsigned char> > setConnected;
  736. {
  737. @@ -1295,7 +1380,16 @@ void ThreadOpenConnections2(void* parg)
  738. }
  739.  
  740. if (addrConnect.IsValid())
  741. - OpenNetworkConnection(addrConnect);
  742. + {
  743. + if (HubModes[nHubMode][HM_MULTITHREAD]==0)
  744. + {
  745. + vnThreadsRunning[THREAD_CONNECT]++;
  746. + OpenNetworkConnection(addrConnect);
  747. + vnThreadsRunning[THREAD_CONNECT]--;
  748. + }
  749. + else
  750. + CreateThread(ONCThread, new CAddress(addrConnect));
  751. + }
  752. }
  753. }
  754.  
  755. @@ -1384,9 +1478,9 @@ bool OpenNetworkConnection(const CAddres
  756. FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect))
  757. return false;
  758.  
  759. - vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
  760. + vnThreadsRunning[THREAD_CONNECT]--;
  761. CNode* pnode = ConnectNode(addrConnect);
  762. - vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
  763. + vnThreadsRunning[THREAD_CONNECT]++;
  764. if (fShutdown)
  765. return false;
  766. if (!pnode)
  767. @@ -1436,6 +1530,10 @@ void ThreadMessageHandler2(void* parg)
  768. pnode->AddRef();
  769. }
  770.  
  771. + mWorkNotification.lock();
  772. + fWorkFound = false;
  773. + mWorkNotification.unlock();
  774. +
  775. // Poll the connected nodes for messages
  776. CNode* pnodeTrickle = NULL;
  777. if (!vNodesCopy.empty())
  778. @@ -1445,8 +1543,13 @@ void ThreadMessageHandler2(void* parg)
  779. // Receive messages
  780. {
  781. TRY_LOCK(pnode->cs_vRecv, lockRecv);
  782. - if (lockRecv)
  783. - ProcessMessages(pnode);
  784. + if (lockRecv) {
  785. + if (pnode->fNeedProcess)
  786. + {
  787. + pnode->fNeedProcess = false;
  788. + ProcessMessages(pnode);
  789. + }
  790. + }
  791. }
  792. if (fShutdown)
  793. return;
  794. @@ -1471,7 +1574,12 @@ void ThreadMessageHandler2(void* parg)
  795. // Reduce vnThreadsRunning so StopNode has permission to exit while
  796. // we're sleeping, but we must always check fShutdown after doing this.
  797. vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
  798. - Sleep(100);
  799. + { // CAUTION: Raising the delay will slow connection accept
  800. + boost::posix_time::time_duration wait_duration = boost::posix_time::millisec(250);
  801. + boost::unique_lock<boost::mutex> lock(mWorkNotification);
  802. + if(!fWorkFound)
  803. + cvWorkNotification.timed_wait(lock, wait_duration);
  804. + }
  805. if (fRequestShutdown)
  806. Shutdown(NULL);
  807. vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
  808. @@ -1706,6 +1814,8 @@ bool StopNode()
  809. if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
  810. if (vnThreadsRunning[THREAD_MINER] > 0) printf("ThreadBitcoinMiner still running\n");
  811. if (vnThreadsRunning[THREAD_RPCSERVER] > 0) printf("ThreadRPCServer still running\n");
  812. + if (vnThreadsRunning[THREAD_CONNECT] > 0) printf("ThreadConnect still running\n");
  813. + if (vnThreadsRunning[THREAD_RPCSERVER0] > 0) printf("ThreadRPCServer0 still running\n");
  814. if (fHaveUPnP && vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
  815. if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
  816. if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
  817. diff -Nurp src.old/net.h src/net.h
  818. --- src.old/net.h 2012-04-25 00:42:11.482004955 -0700
  819. +++ src/net.h 2012-04-26 18:04:42.161964416 -0700
  820. @@ -8,6 +8,7 @@
  821. #include <deque>
  822. #include <boost/array.hpp>
  823. #include <boost/foreach.hpp>
  824. +#include <boost/detail/atomic_count.hpp>
  825. #include <openssl/rand.h>
  826.  
  827. #ifndef WIN32
  828. @@ -74,6 +75,8 @@ enum threadId
  829. THREAD_MESSAGEHANDLER,
  830. THREAD_MINER,
  831. THREAD_RPCSERVER,
  832. + THREAD_CONNECT,
  833. + THREAD_RPCSERVER0,
  834. THREAD_UPNP,
  835. THREAD_DNSSEED,
  836. THREAD_ADDEDCONNECTIONS,
  837. @@ -87,7 +90,18 @@ extern bool fAllowDNS;
  838. extern uint64 nLocalServices;
  839. extern CAddress addrLocalHost;
  840. extern uint64 nLocalHostNonce;
  841. -extern boost::array<int, THREAD_MAX> vnThreadsRunning;
  842. +class atomic_long {
  843. + boost::detail::atomic_count val;
  844. +
  845. +public:
  846. + atomic_long(): val(0) {}
  847. + void operator++() { ++val; }
  848. + long operator--() { return --val; }
  849. + void operator++(int i) { ++val; }
  850. + void operator--(int i) { --val; }
  851. + operator long() const { return val; }
  852. +};
  853. +extern boost::array<atomic_long, THREAD_MAX> vnThreadsRunning;
  854. extern CAddrMan addrman;
  855.  
  856. extern std::vector<CNode*> vNodes;
  857. @@ -127,6 +141,7 @@ public:
  858. bool fNetworkNode;
  859. bool fSuccessfullyConnected;
  860. bool fDisconnect;
  861. + bool fNeedProcess;
  862. protected:
  863. int nRefCount;
  864.  
  865. @@ -175,6 +190,7 @@ public:
  866. fNetworkNode = false;
  867. fSuccessfullyConnected = false;
  868. fDisconnect = false;
  869. + fNeedProcess = false;
  870. nRefCount = 0;
  871. nReleaseTime = 0;
  872. hashContinue = 0;
  873. diff -Nurp src.old/util.cpp src/util.cpp
  874. --- src.old/util.cpp 2012-04-25 00:42:11.501964285 -0700
  875. +++ src/util.cpp 2012-04-26 18:04:42.161964416 -0700
  876. @@ -65,7 +65,7 @@ bool fShutdown = false;
  877. bool fDaemon = false;
  878. bool fServer = false;
  879. bool fCommandLine = false;
  880. -string strMiscWarning;
  881. +string strMiscWarning, strRPCUser, strRPCPass;
  882. bool fTestNet = false;
  883. bool fNoListen = false;
  884. bool fLogTimestamps = false;
  885. diff -Nurp src.old/util.h src/util.h
  886. --- src.old/util.h 2012-04-25 00:42:11.501964285 -0700
  887. +++ src/util.h 2012-04-26 18:04:42.161964416 -0700
  888. @@ -121,7 +121,7 @@ extern bool fShutdown;
  889. extern bool fDaemon;
  890. extern bool fServer;
  891. extern bool fCommandLine;
  892. -extern std::string strMiscWarning;
  893. +extern std::string strMiscWarning, strRPCUser, strRPCPass;
  894. extern bool fTestNet;
  895. extern bool fNoListen;
  896. extern bool fLogTimestamps;
  897. @@ -705,7 +705,7 @@ inline void SetThreadPriority(int nPrior
  898.  
  899. inline void ExitThread(size_t nExitCode)
  900. {
  901. - pthread_exit((void*)nExitCode);
  902. + pthread_exit((void*)(uintptr_t)nExitCode);
  903. }
  904. #endif
Add Comment
Please, Sign In to add comment