Guest User

4diff-0.6.0

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