Last active
February 3, 2016 14:55
-
-
Save polarbeard/db7909cba265c3c50c02 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -uNr a/bitcoin/src/bitcoinrpc.cpp b/bitcoin/src/bitcoinrpc.cpp | |
--- a/bitcoin/src/bitcoinrpc.cpp ede2e19dd0ce3d03f54689cbeda30b4b36152f7e532b3d34f0f8c55bb292f7d25c149b88162d96a8208997237a32566d0e555aa7105bfed8175983d80ad892e6 | |
+++ b/bitcoin/src/bitcoinrpc.cpp a71655bcd21408123e7be15f91803707bafca212787544d3e160855c170d596029847dc35ecd0f4dbe10f8e412bee114fba803d4e369c980d06691373106c18d | |
@@ -196,6 +196,42 @@ | |
return (int)vNodes.size(); | |
} | |
+Value getpeerinfo(const Array& params, bool fHelp) | |
+{ | |
+ if (fHelp || params.size() != 0) | |
+ throw runtime_error( | |
+ "getpeerinfo\n" | |
+ "Returns data about each connected network node."); | |
+ | |
+ Array ret; | |
+ | |
+ CRITICAL_BLOCK(cs_vNodes) | |
+ { | |
+ BOOST_FOREACH(CNode* pnode, vNodes) | |
+ { | |
+ CNodeStats stats; | |
+ pnode->CopyStats(stats); | |
+ | |
+ Object obj; | |
+ obj.push_back(Pair("addr", stats.addr.ToString())); | |
+ obj.push_back(Pair("services", strprintf("%08"PRI64x, stats.nServices))); | |
+ obj.push_back(Pair("lastsend", (boost::int64_t)stats.nLastSend)); | |
+ obj.push_back(Pair("lastrecv", (boost::int64_t)stats.nLastRecv)); | |
+ obj.push_back(Pair("conntime", (boost::int64_t)stats.nTimeConnected)); | |
+ obj.push_back(Pair("version", stats.nVersion)); | |
+ obj.push_back(Pair("subver", stats.strSubVer)); | |
+ obj.push_back(Pair("inbound", stats.fInbound)); | |
+ obj.push_back(Pair("releasetime", (boost::int64_t)stats.nReleaseTime)); | |
+ obj.push_back(Pair("height", stats.nStartingHeight)); | |
+ obj.push_back(Pair("banscore", stats.nMisbehavior)); | |
+ | |
+ ret.push_back(obj); | |
+ } | |
+ } | |
+ | |
+ return ret; | |
+} | |
+ | |
double GetDifficulty() | |
{ | |
@@ -1850,6 +1886,7 @@ | |
make_pair("getblockcount", &getblockcount), | |
make_pair("getblocknumber", &getblocknumber), | |
make_pair("getconnectioncount", &getconnectioncount), | |
+ make_pair("getpeerinfo", &getpeerinfo), | |
make_pair("getdifficulty", &getdifficulty), | |
make_pair("getgenerate", &getgenerate), | |
make_pair("setgenerate", &setgenerate), | |
@@ -1897,6 +1934,7 @@ | |
"getblockcount", | |
"getblocknumber", // deprecated | |
"getconnectioncount", | |
+ "getpeerinfo", | |
"getdifficulty", | |
"getgenerate", | |
"setgenerate", | |
diff -uNr a/bitcoin/src/net.cpp b/bitcoin/src/net.cpp | |
--- a/bitcoin/src/net.cpp 31eb2cbdf4f83f10ae8a7cdd3a69312ba6eafbecfafbeddf7546ce99847bd4f2a674037e2b89a0a7b91c37127d9770501c265a7977edb0ae0b3a5964272692f9 | |
+++ b/bitcoin/src/net.cpp 107ef79a59c51c006cbdb3f7a1e6c48771773c935b023da6459564f0485a0ae7701acfe8551b8bad4b2d5f7826ae2b9166a7e8373157d2afe84ba05b26310838 | |
@@ -577,16 +577,20 @@ | |
return false; | |
} | |
- | |
- | |
- | |
- | |
- | |
- | |
- | |
- | |
- | |
- | |
+void CNode::CopyStats(CNodeStats &stats) | |
+{ | |
+ stats.nServices = nServices; | |
+ stats.nLastSend = nLastSend; | |
+ stats.nLastRecv = nLastRecv; | |
+ stats.nTimeConnected = nTimeConnected; | |
+ stats.addr = addr; | |
+ stats.nVersion = nVersion; | |
+ stats.strSubVer = strSubVer; | |
+ stats.fInbound = fInbound; | |
+ stats.nReleaseTime = nReleaseTime; | |
+ stats.nStartingHeight = nStartingHeight; | |
+ stats.nMisbehavior = nMisbehavior; | |
+} | |
void ThreadSocketHandler(void* parg) | |
{ | |
diff -uNr a/bitcoin/src/net.h b/bitcoin/src/net.h | |
--- a/bitcoin/src/net.h bb842420bcc67752edf8e658524b135f499c5f8676557a6c12f47f204303e34bd73beabdf6e9146ba452947c4e5cd298529969fab90f16942f6bf0c1229f7043 | |
+++ b/bitcoin/src/net.h 77ede4a59510c44c7167144c78cc0608430c50ff25b28201eb39ee69b0d4acbcce7374c4efd254304732c409b5799bc59557c3cb69a29c9f7c29ddd3d9e3a4a6 | |
@@ -87,10 +87,21 @@ | |
extern int fUseProxy; | |
extern CAddress addrProxy; | |
- | |
- | |
- | |
- | |
+class CNodeStats | |
+{ | |
+public: | |
+ uint64 nServices; | |
+ int64 nLastSend; | |
+ int64 nLastRecv; | |
+ int64 nTimeConnected; | |
+ CAddress addr; | |
+ int nVersion; | |
+ std::string strSubVer; | |
+ bool fInbound; | |
+ int64 nReleaseTime; | |
+ int nStartingHeight; | |
+ int nMisbehavior; | |
+}; | |
class CNode | |
{ | |
@@ -590,6 +601,7 @@ | |
static void ClearBanned(); // needed for unit testing | |
static bool IsBanned(unsigned int ip); | |
bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot | |
+ void CopyStats(CNodeStats &stats); | |
}; | |
diff -uNr a/bitcoin/src/net.h.orig b/bitcoin/src/net.h.orig | |
--- a/bitcoin/src/net.h.orig false | |
+++ b/bitcoin/src/net.h.orig bb842420bcc67752edf8e658524b135f499c5f8676557a6c12f47f204303e34bd73beabdf6e9146ba452947c4e5cd298529969fab90f16942f6bf0c1229f7043 | |
@@ -0,0 +1,696 @@ | |
+// Copyright (c) 2009-2010 Satoshi Nakamoto | |
+// Copyright (c) 2009-2012 The Bitcoin developers | |
+// Distributed under the MIT/X11 software license, see the accompanying | |
+// file license.txt or http://www.opensource.org/licenses/mit-license.php. | |
+#ifndef BITCOIN_NET_H | |
+#define BITCOIN_NET_H | |
+ | |
+#include <deque> | |
+#include <boost/array.hpp> | |
+#include <boost/foreach.hpp> | |
+#include <openssl/rand.h> | |
+ | |
+#include "protocol.h" | |
+ | |
+class CAddrDB; | |
+class CRequestTracker; | |
+class CNode; | |
+class CBlockIndex; | |
+extern int nBestHeight; | |
+extern int nConnectTimeout; | |
+ | |
+ | |
+ | |
+inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer", 10*1000); } | |
+inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); } | |
+static const unsigned int PUBLISH_HOPS = 5; | |
+ | |
+bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout=nConnectTimeout); | |
+bool Lookup(const char *pszName, std::vector<CAddress>& vaddr, int nServices, int nMaxSolutions, int portDefault = 0, bool fAllowPort = false); | |
+bool Lookup(const char *pszName, CAddress& addr, int nServices, int portDefault = 0, bool fAllowPort = false); | |
+bool AddAddress(CAddress addr, int64 nTimePenalty=0, CAddrDB *pAddrDB=NULL); | |
+void AddressCurrentlyConnected(const CAddress& addr); | |
+CNode* FindNode(unsigned int ip); | |
+CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0); | |
+void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1); | |
+bool AnySubscribed(unsigned int nChannel); | |
+void MapPort(bool fMapPort); | |
+bool BindListenPort(std::string& strError=REF(std::string())); | |
+void StartNode(void* parg); | |
+bool StopNode(); | |
+ | |
+enum | |
+{ | |
+ MSG_TX = 1, | |
+ MSG_BLOCK, | |
+}; | |
+ | |
+class CRequestTracker | |
+{ | |
+public: | |
+ void (*fn)(void*, CDataStream&); | |
+ void* param1; | |
+ | |
+ explicit CRequestTracker(void (*fnIn)(void*, CDataStream&)=NULL, void* param1In=NULL) | |
+ { | |
+ fn = fnIn; | |
+ param1 = param1In; | |
+ } | |
+ | |
+ bool IsNull() | |
+ { | |
+ return fn == NULL; | |
+ } | |
+}; | |
+ | |
+ | |
+ | |
+ | |
+ | |
+extern bool fClient; | |
+extern bool fAllowDNS; | |
+extern uint64 nLocalServices; | |
+extern CAddress addrLocalHost; | |
+extern uint64 nLocalHostNonce; | |
+extern boost::array<int, 10> vnThreadsRunning; | |
+ | |
+extern std::vector<CNode*> vNodes; | |
+extern CCriticalSection cs_vNodes; | |
+extern std::map<std::vector<unsigned char>, CAddress> mapAddresses; | |
+extern CCriticalSection cs_mapAddresses; | |
+extern std::map<CInv, CDataStream> mapRelay; | |
+extern std::deque<std::pair<int64, CInv> > vRelayExpiration; | |
+extern CCriticalSection cs_mapRelay; | |
+extern std::map<CInv, int64> mapAlreadyAskedFor; | |
+ | |
+// Settings | |
+extern int fUseProxy; | |
+extern CAddress addrProxy; | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+class CNode | |
+{ | |
+public: | |
+ // socket | |
+ uint64 nServices; | |
+ SOCKET hSocket; | |
+ CDataStream vSend; | |
+ CDataStream vRecv; | |
+ CCriticalSection cs_vSend; | |
+ CCriticalSection cs_vRecv; | |
+ int64 nLastSend; | |
+ int64 nLastRecv; | |
+ int64 nLastSendEmpty; | |
+ int64 nTimeConnected; | |
+ unsigned int nHeaderStart; | |
+ unsigned int nMessageStart; | |
+ CAddress addr; | |
+ int nVersion; | |
+ std::string strSubVer; | |
+ bool fClient; | |
+ bool fInbound; | |
+ bool fNetworkNode; | |
+ bool fSuccessfullyConnected; | |
+ bool fDisconnect; | |
+protected: | |
+ int nRefCount; | |
+ | |
+ // Denial-of-service detection/prevention | |
+ // Key is ip address, value is banned-until-time | |
+ static std::map<unsigned int, int64> setBanned; | |
+ static CCriticalSection cs_setBanned; | |
+ int nMisbehavior; | |
+ | |
+public: | |
+ int64 nReleaseTime; | |
+ std::map<uint256, CRequestTracker> mapRequests; | |
+ CCriticalSection cs_mapRequests; | |
+ uint256 hashContinue; | |
+ CBlockIndex* pindexLastGetBlocksBegin; | |
+ uint256 hashLastGetBlocksEnd; | |
+ int nStartingHeight; | |
+ | |
+ // flood relay | |
+ std::vector<CAddress> vAddrToSend; | |
+ std::set<CAddress> setAddrKnown; | |
+ bool fGetAddr; | |
+ std::set<uint256> setKnown; | |
+ | |
+ // inventory based relay | |
+ std::set<CInv> setInventoryKnown; | |
+ std::vector<CInv> vInventoryToSend; | |
+ CCriticalSection cs_inventory; | |
+ std::multimap<int64, CInv> mapAskFor; | |
+ | |
+ // publish and subscription | |
+ std::vector<char> vfSubscribe; | |
+ | |
+ CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false) | |
+ { | |
+ nServices = 0; | |
+ hSocket = hSocketIn; | |
+ vSend.SetType(SER_NETWORK); | |
+ vSend.SetVersion(0); | |
+ vRecv.SetType(SER_NETWORK); | |
+ vRecv.SetVersion(0); | |
+ // Version 0.2 obsoletes 20 Feb 2012 | |
+ if (GetTime() > 1329696000) | |
+ { | |
+ vSend.SetVersion(209); | |
+ vRecv.SetVersion(209); | |
+ } | |
+ nLastSend = 0; | |
+ nLastRecv = 0; | |
+ nLastSendEmpty = GetTime(); | |
+ nTimeConnected = GetTime(); | |
+ nHeaderStart = -1; | |
+ nMessageStart = -1; | |
+ addr = addrIn; | |
+ nVersion = 0; | |
+ strSubVer = ""; | |
+ fClient = false; // set by version message | |
+ fInbound = fInboundIn; | |
+ fNetworkNode = false; | |
+ fSuccessfullyConnected = false; | |
+ fDisconnect = false; | |
+ nRefCount = 0; | |
+ nReleaseTime = 0; | |
+ hashContinue = 0; | |
+ pindexLastGetBlocksBegin = 0; | |
+ hashLastGetBlocksEnd = 0; | |
+ nStartingHeight = -1; | |
+ fGetAddr = false; | |
+ vfSubscribe.assign(256, false); | |
+ nMisbehavior = 0; | |
+ | |
+ // Be shy and don't send version until we hear | |
+ if (!fInbound) | |
+ PushVersion(); | |
+ } | |
+ | |
+ ~CNode() | |
+ { | |
+ if (hSocket != INVALID_SOCKET) | |
+ { | |
+ closesocket(hSocket); | |
+ hSocket = INVALID_SOCKET; | |
+ } | |
+ } | |
+ | |
+private: | |
+ CNode(const CNode&); | |
+ void operator=(const CNode&); | |
+public: | |
+ | |
+ | |
+ int GetRefCount() | |
+ { | |
+ return std::max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0); | |
+ } | |
+ | |
+ CNode* AddRef(int64 nTimeout=0) | |
+ { | |
+ if (nTimeout != 0) | |
+ nReleaseTime = std::max(nReleaseTime, GetTime() + nTimeout); | |
+ else | |
+ nRefCount++; | |
+ return this; | |
+ } | |
+ | |
+ void Release() | |
+ { | |
+ nRefCount--; | |
+ } | |
+ | |
+ | |
+ | |
+ void AddAddressKnown(const CAddress& addr) | |
+ { | |
+ setAddrKnown.insert(addr); | |
+ } | |
+ | |
+ void PushAddress(const CAddress& addr) | |
+ { | |
+ // Known checking here is only to save space from duplicates. | |
+ // SendMessages will filter it again for knowns that were added | |
+ // after addresses were pushed. | |
+ if (addr.IsValid() && !setAddrKnown.count(addr)) | |
+ vAddrToSend.push_back(addr); | |
+ } | |
+ | |
+ | |
+ void AddInventoryKnown(const CInv& inv) | |
+ { | |
+ CRITICAL_BLOCK(cs_inventory) | |
+ setInventoryKnown.insert(inv); | |
+ } | |
+ | |
+ void PushInventory(const CInv& inv) | |
+ { | |
+ CRITICAL_BLOCK(cs_inventory) | |
+ if (!setInventoryKnown.count(inv)) | |
+ vInventoryToSend.push_back(inv); | |
+ } | |
+ | |
+ void AskFor(const CInv& inv) | |
+ { | |
+ // We're using mapAskFor as a priority queue, | |
+ // the key is the earliest time the request can be sent | |
+ int64& nRequestTime = mapAlreadyAskedFor[inv]; | |
+ printf("askfor %s %"PRI64d"\n", inv.ToString().c_str(), nRequestTime); | |
+ | |
+ // Make sure not to reuse time indexes to keep things in the same order | |
+ int64 nNow = (GetTime() - 1) * 1000000; | |
+ static int64 nLastTime; | |
+ ++nLastTime; | |
+ nNow = std::max(nNow, nLastTime); | |
+ nLastTime = nNow; | |
+ | |
+ // Each retry is 2 minutes after the last | |
+ nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow); | |
+ mapAskFor.insert(std::make_pair(nRequestTime, inv)); | |
+ } | |
+ | |
+ | |
+ | |
+ void BeginMessage(const char* pszCommand) | |
+ { | |
+ ENTER_CRITICAL_SECTION(cs_vSend); | |
+ if (nHeaderStart != -1) | |
+ AbortMessage(); | |
+ nHeaderStart = vSend.size(); | |
+ vSend << CMessageHeader(pszCommand, 0); | |
+ nMessageStart = vSend.size(); | |
+ if (fDebug) { | |
+ printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str()); | |
+ printf("sending: %s ", pszCommand); | |
+ } | |
+ } | |
+ | |
+ void AbortMessage() | |
+ { | |
+ if (nHeaderStart == -1) | |
+ return; | |
+ vSend.resize(nHeaderStart); | |
+ nHeaderStart = -1; | |
+ nMessageStart = -1; | |
+ LEAVE_CRITICAL_SECTION(cs_vSend); | |
+ | |
+ if (fDebug) | |
+ printf("(aborted)\n"); | |
+ } | |
+ | |
+ void EndMessage() | |
+ { | |
+ if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0) | |
+ { | |
+ printf("dropmessages DROPPING SEND MESSAGE\n"); | |
+ AbortMessage(); | |
+ return; | |
+ } | |
+ | |
+ if (nHeaderStart == -1) | |
+ return; | |
+ | |
+ // Set the size | |
+ unsigned int nSize = vSend.size() - nMessageStart; | |
+ memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize)); | |
+ | |
+ // Set the checksum | |
+ if (vSend.GetVersion() >= 209) | |
+ { | |
+ uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end()); | |
+ unsigned int nChecksum = 0; | |
+ memcpy(&nChecksum, &hash, sizeof(nChecksum)); | |
+ assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum)); | |
+ memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum)); | |
+ } | |
+ | |
+ if (fDebug) { | |
+ printf("(%d bytes)\n", nSize); | |
+ } | |
+ | |
+ nHeaderStart = -1; | |
+ nMessageStart = -1; | |
+ LEAVE_CRITICAL_SECTION(cs_vSend); | |
+ } | |
+ | |
+ void EndMessageAbortIfEmpty() | |
+ { | |
+ if (nHeaderStart == -1) | |
+ return; | |
+ int nSize = vSend.size() - nMessageStart; | |
+ if (nSize > 0) | |
+ EndMessage(); | |
+ else | |
+ AbortMessage(); | |
+ } | |
+ | |
+ | |
+ | |
+ void PushVersion() | |
+ { | |
+ /// when NTP implemented, change to just nTime = GetAdjustedTime() | |
+ int64 nTime = (fInbound ? GetAdjustedTime() : GetTime()); | |
+ CAddress addrYou = (fUseProxy ? CAddress("0.0.0.0") : addr); | |
+ CAddress addrMe = (fUseProxy || !addrLocalHost.IsRoutable() ? CAddress("0.0.0.0") : addrLocalHost); | |
+ RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); | |
+ PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe, | |
+ nLocalHostNonce, FormatSubVersion(CLIENT_NAME, VERSION), nBestHeight); | |
+ } | |
+ | |
+ | |
+ | |
+ | |
+ void PushMessage(const char* pszCommand) | |
+ { | |
+ try | |
+ { | |
+ BeginMessage(pszCommand); | |
+ EndMessage(); | |
+ } | |
+ catch (...) | |
+ { | |
+ AbortMessage(); | |
+ throw; | |
+ } | |
+ } | |
+ | |
+ template<typename T1> | |
+ void PushMessage(const char* pszCommand, const T1& a1) | |
+ { | |
+ try | |
+ { | |
+ BeginMessage(pszCommand); | |
+ vSend << a1; | |
+ EndMessage(); | |
+ } | |
+ catch (...) | |
+ { | |
+ AbortMessage(); | |
+ throw; | |
+ } | |
+ } | |
+ | |
+ template<typename T1, typename T2> | |
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2) | |
+ { | |
+ try | |
+ { | |
+ BeginMessage(pszCommand); | |
+ vSend << a1 << a2; | |
+ EndMessage(); | |
+ } | |
+ catch (...) | |
+ { | |
+ AbortMessage(); | |
+ throw; | |
+ } | |
+ } | |
+ | |
+ template<typename T1, typename T2, typename T3> | |
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3) | |
+ { | |
+ try | |
+ { | |
+ BeginMessage(pszCommand); | |
+ vSend << a1 << a2 << a3; | |
+ EndMessage(); | |
+ } | |
+ catch (...) | |
+ { | |
+ AbortMessage(); | |
+ throw; | |
+ } | |
+ } | |
+ | |
+ template<typename T1, typename T2, typename T3, typename T4> | |
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4) | |
+ { | |
+ try | |
+ { | |
+ BeginMessage(pszCommand); | |
+ vSend << a1 << a2 << a3 << a4; | |
+ EndMessage(); | |
+ } | |
+ catch (...) | |
+ { | |
+ AbortMessage(); | |
+ throw; | |
+ } | |
+ } | |
+ | |
+ template<typename T1, typename T2, typename T3, typename T4, typename T5> | |
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5) | |
+ { | |
+ try | |
+ { | |
+ BeginMessage(pszCommand); | |
+ vSend << a1 << a2 << a3 << a4 << a5; | |
+ EndMessage(); | |
+ } | |
+ catch (...) | |
+ { | |
+ AbortMessage(); | |
+ throw; | |
+ } | |
+ } | |
+ | |
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> | |
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6) | |
+ { | |
+ try | |
+ { | |
+ BeginMessage(pszCommand); | |
+ vSend << a1 << a2 << a3 << a4 << a5 << a6; | |
+ EndMessage(); | |
+ } | |
+ catch (...) | |
+ { | |
+ AbortMessage(); | |
+ throw; | |
+ } | |
+ } | |
+ | |
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7> | |
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7) | |
+ { | |
+ try | |
+ { | |
+ BeginMessage(pszCommand); | |
+ vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7; | |
+ EndMessage(); | |
+ } | |
+ catch (...) | |
+ { | |
+ AbortMessage(); | |
+ throw; | |
+ } | |
+ } | |
+ | |
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> | |
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8) | |
+ { | |
+ try | |
+ { | |
+ BeginMessage(pszCommand); | |
+ vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8; | |
+ EndMessage(); | |
+ } | |
+ catch (...) | |
+ { | |
+ AbortMessage(); | |
+ throw; | |
+ } | |
+ } | |
+ | |
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9> | |
+ void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9) | |
+ { | |
+ try | |
+ { | |
+ BeginMessage(pszCommand); | |
+ vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9; | |
+ EndMessage(); | |
+ } | |
+ catch (...) | |
+ { | |
+ AbortMessage(); | |
+ throw; | |
+ } | |
+ } | |
+ | |
+ | |
+ void PushRequest(const char* pszCommand, | |
+ void (*fn)(void*, CDataStream&), void* param1) | |
+ { | |
+ uint256 hashReply; | |
+ RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); | |
+ | |
+ CRITICAL_BLOCK(cs_mapRequests) | |
+ mapRequests[hashReply] = CRequestTracker(fn, param1); | |
+ | |
+ PushMessage(pszCommand, hashReply); | |
+ } | |
+ | |
+ template<typename T1> | |
+ void PushRequest(const char* pszCommand, const T1& a1, | |
+ void (*fn)(void*, CDataStream&), void* param1) | |
+ { | |
+ uint256 hashReply; | |
+ RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); | |
+ | |
+ CRITICAL_BLOCK(cs_mapRequests) | |
+ mapRequests[hashReply] = CRequestTracker(fn, param1); | |
+ | |
+ PushMessage(pszCommand, hashReply, a1); | |
+ } | |
+ | |
+ template<typename T1, typename T2> | |
+ void PushRequest(const char* pszCommand, const T1& a1, const T2& a2, | |
+ void (*fn)(void*, CDataStream&), void* param1) | |
+ { | |
+ uint256 hashReply; | |
+ RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); | |
+ | |
+ CRITICAL_BLOCK(cs_mapRequests) | |
+ mapRequests[hashReply] = CRequestTracker(fn, param1); | |
+ | |
+ PushMessage(pszCommand, hashReply, a1, a2); | |
+ } | |
+ | |
+ | |
+ | |
+ void PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd); | |
+ bool IsSubscribed(unsigned int nChannel); | |
+ void Subscribe(unsigned int nChannel, unsigned int nHops=0); | |
+ void CancelSubscribe(unsigned int nChannel); | |
+ void CloseSocketDisconnect(); | |
+ void Cleanup(); | |
+ | |
+ | |
+ // Denial-of-service detection/prevention | |
+ // The idea is to detect peers that are behaving | |
+ // badly and disconnect/ban them, but do it in a | |
+ // one-coding-mistake-won't-shatter-the-entire-network | |
+ // way. | |
+ // IMPORTANT: There should be nothing I can give a | |
+ // node that it will forward on that will make that | |
+ // node's peers drop it. If there is, an attacker | |
+ // can isolate a node and/or try to split the network. | |
+ // Dropping a node for sending stuff that is invalid | |
+ // now but might be valid in a later version is also | |
+ // dangerous, because it can cause a network split | |
+ // between nodes running old code and nodes running | |
+ // new code. | |
+ static void ClearBanned(); // needed for unit testing | |
+ static bool IsBanned(unsigned int ip); | |
+ bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot | |
+}; | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+inline void RelayInventory(const CInv& inv) | |
+{ | |
+ // Put on lists to offer to the other nodes | |
+ CRITICAL_BLOCK(cs_vNodes) | |
+ BOOST_FOREACH(CNode* pnode, vNodes) | |
+ pnode->PushInventory(inv); | |
+} | |
+ | |
+template<typename T> | |
+void RelayMessage(const CInv& inv, const T& a) | |
+{ | |
+ CDataStream ss(SER_NETWORK); | |
+ ss.reserve(10000); | |
+ ss << a; | |
+ RelayMessage(inv, ss); | |
+} | |
+ | |
+template<> | |
+inline void RelayMessage<>(const CInv& inv, const CDataStream& ss) | |
+{ | |
+ CRITICAL_BLOCK(cs_mapRelay) | |
+ { | |
+ // Expire old relay messages | |
+ while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime()) | |
+ { | |
+ mapRelay.erase(vRelayExpiration.front().second); | |
+ vRelayExpiration.pop_front(); | |
+ } | |
+ | |
+ // Save original serialized message so newer versions are preserved | |
+ mapRelay[inv] = ss; | |
+ vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv)); | |
+ } | |
+ | |
+ RelayInventory(inv); | |
+} | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+// | |
+// Templates for the publish and subscription system. | |
+// The object being published as T& obj needs to have: | |
+// a set<unsigned int> setSources member | |
+// specializations of AdvertInsert and AdvertErase | |
+// Currently implemented for CTable and CProduct. | |
+// | |
+ | |
+template<typename T> | |
+void AdvertStartPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj) | |
+{ | |
+ // Add to sources | |
+ obj.setSources.insert(pfrom->addr.ip); | |
+ | |
+ if (!AdvertInsert(obj)) | |
+ return; | |
+ | |
+ // Relay | |
+ CRITICAL_BLOCK(cs_vNodes) | |
+ BOOST_FOREACH(CNode* pnode, vNodes) | |
+ if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel))) | |
+ pnode->PushMessage("publish", nChannel, nHops, obj); | |
+} | |
+ | |
+template<typename T> | |
+void AdvertStopPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj) | |
+{ | |
+ uint256 hash = obj.GetHash(); | |
+ | |
+ CRITICAL_BLOCK(cs_vNodes) | |
+ BOOST_FOREACH(CNode* pnode, vNodes) | |
+ if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel))) | |
+ pnode->PushMessage("pub-cancel", nChannel, nHops, hash); | |
+ | |
+ AdvertErase(obj); | |
+} | |
+ | |
+template<typename T> | |
+void AdvertRemoveSource(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj) | |
+{ | |
+ // Remove a source | |
+ obj.setSources.erase(pfrom->addr.ip); | |
+ | |
+ // If no longer supported by any sources, cancel it | |
+ if (obj.setSources.empty()) | |
+ AdvertStopPublish(pfrom, nChannel, nHops, obj); | |
+} | |
+ | |
+#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-----BEGIN PGP SIGNATURE----- | |
Version: GnuPG v1 | |
iQIcBAABAgAGBQJWshTiAAoJEBHMkEKSnTaC0CcP/1p/g4qnMLrefr9zpDRwd3gw | |
kGysVspgs6XVAtgm6cY+1PSxHNnH1A7fB00ihmVMjclz2B+NYrITu0bomj4U82hn | |
X21fdPZr5it+3QCo/dIUAF1T+P9zz1RzG2fOgviJsdmWgjccbKFJy2jITBN+G93X | |
jhNNvhG1/SIz4DjBJy9yzBribCrlhDNrIZh9+qpC8KKdWm1jNVh1xzee+3Ihmf6c | |
v70iapj3+fs2/YsgBWDpHkWcVmockekm5x5RT6WC6SSRKpcVRwixDWtViJEzGdtI | |
CGcA5I29pICJs3ZFGp5nJXYTJxzfPgCno6K6c4299nKSgri2BQePqjnOmgI9aUvR | |
Mo+9IrkyU7Ue7/b3kB6gflO0oWZdSdO07c2M3m5F1ZZAswc9pVi+7IDfWLt5OTpf | |
NXZs2imWXdT8aRzlf+b3fJKZKWR3uDLCwWIeNN0EfAl3FFtXiynKDNl+riB9FHo9 | |
BoJMv383YLxqzaWt7CLdpfnTYt9arYUtku5tVBIv6kkYDowNx8/gZNwvu2Gqj3nM | |
jktkQMUjyrUNg64IE80rILfLnGKpymtqL7KL4uwdjYg7R2wlBaueOct8GnQuU6Y1 | |
Z5cg2a8GOdgFUcwa7oLDIyJAtbW7TBl8f7E1yXnWA00fJbtCyBQ7UUdIsG3JBjcm | |
Xv+qpzOe0zoerOpRBUVP | |
=znyv | |
-----END PGP SIGNATURE----- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment