X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=blobdiff_plain;f=src%2Fnet.h;h=c1d478a4258ef0ceca013e27bf3afc7e30f45ad7;hp=f4af93a4953d4030da2465c2067f96534b0752df;hb=28f9882707d389250e307ebf58dcf981340f1381;hpb=a3342d096f3456e5e8d087bb3c8eea8b25eb6b57 diff --git a/src/net.h b/src/net.h index f4af93a..c1d478a 100644 --- a/src/net.h +++ b/src/net.h @@ -1,7 +1,7 @@ // 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. +// file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_NET_H #define BITCOIN_NET_H @@ -14,10 +14,12 @@ #include #endif +#include "mruset.h" #include "netbase.h" #include "protocol.h" +#include "addrman.h" +#include "hash.h" -class CAddrDB; class CRequestTracker; class CNode; class CBlockIndex; @@ -25,26 +27,50 @@ extern int nBestHeight; -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; +inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); } +inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); } +void AddOneShot(std::string strDest); bool RecvLine(SOCKET hSocket, std::string& strLine); bool GetMyExternalIP(CNetAddr& ipRet); -bool AddAddress(CAddress addr, int64 nTimePenalty=0, CAddrDB *pAddrDB=NULL); void AddressCurrentlyConnected(const CService& addr); CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CService& 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())); +CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL, int64 nTimeout=0); +void MapPort(); +unsigned short GetListenPort(); +bool BindListenPort(const CService &bindAddr, std::string& strError=REF(std::string())); void StartNode(void* parg); bool StopNode(); enum { + LOCAL_NONE, // unknown + LOCAL_IF, // address a local interface listens on + LOCAL_BIND, // address explicit bound to + LOCAL_UPNP, // address reported by UPnP + LOCAL_IRC, // address reported by IRC (deprecated) + LOCAL_HTTP, // address reported by whatismyip.com and similar + LOCAL_MANUAL, // address explicitly specified (-externalip=) + + LOCAL_MAX +}; + +void SetLimited(enum Network net, bool fLimited = true); +bool IsLimited(enum Network net); +bool IsLimited(const CNetAddr& addr); +bool AddLocal(const CService& addr, int nScore = LOCAL_NONE); +bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE); +bool SeenLocal(const CService& addr); +bool IsLocal(const CService& addr); +bool GetLocal(CService &addr, const CNetAddr *paddrPeer = NULL); +bool IsReachable(const CNetAddr &addr); +void SetReachable(enum Network net, bool fFlag = true); +CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL); + + +enum +{ MSG_TX = 1, MSG_BLOCK, }; @@ -68,32 +94,35 @@ public: }; - +/** Thread types */ enum threadId { THREAD_SOCKETHANDLER, THREAD_OPENCONNECTIONS, THREAD_MESSAGEHANDLER, - THREAD_MINER, - THREAD_RPCSERVER, + THREAD_RPCLISTENER, THREAD_UPNP, THREAD_DNSSEED, THREAD_ADDEDCONNECTIONS, + THREAD_DUMPADDRESS, + THREAD_RPCHANDLER, + THREAD_MINTER, + THREAD_SCRIPTCHECK, THREAD_MAX }; extern bool fClient; -extern bool fAllowDNS; +extern bool fDiscover; +extern bool fUseUPnP; extern uint64 nLocalServices; -extern CAddress addrLocalHost; extern uint64 nLocalHostNonce; +extern CAddress addrSeenByPeer; extern boost::array vnThreadsRunning; +extern CAddrMan addrman; extern std::vector vNodes; extern CCriticalSection cs_vNodes; -extern std::map, CAddress> mapAddresses; -extern CCriticalSection cs_mapAddresses; extern std::map mapRelay; extern std::deque > vRelayExpiration; extern CCriticalSection cs_mapRelay; @@ -102,9 +131,27 @@ extern std::map mapAlreadyAskedFor; +class CNodeStats +{ +public: + uint64 nServices; + int64 nLastSend; + int64 nLastRecv; + int64 nTimeConnected; + std::string addrName; + int nVersion; + std::string strSubVer; + bool fInbound; + int64 nReleaseTime; + int nStartingHeight; + int nMisbehavior; +}; + + +/** Information about a peer */ class CNode { public: @@ -119,21 +166,25 @@ public: int64 nLastRecv; int64 nLastSendEmpty; int64 nTimeConnected; - unsigned int nHeaderStart; + int nHeaderStart; unsigned int nMessageStart; CAddress addr; + std::string addrName; + CService addrLocal; int nVersion; std::string strSubVer; + bool fOneShot; bool fClient; bool fInbound; bool fNetworkNode; bool fSuccessfullyConnected; bool fDisconnect; + CSemaphoreGrant grantOutbound; protected: int nRefCount; // Denial-of-service detection/prevention - // Key is ip address, value is banned-until-time + // Key is IP address, value is banned-until-time static std::map setBanned; static CCriticalSection cs_setBanned; int nMisbehavior; @@ -146,36 +197,25 @@ public: CBlockIndex* pindexLastGetBlocksBegin; uint256 hashLastGetBlocksEnd; int nStartingHeight; + bool fStartSync; // flood relay std::vector vAddrToSend; std::set setAddrKnown; bool fGetAddr; std::set setKnown; + uint256 hashCheckpointKnown; // ppcoin: known sent sync-checkpoint // inventory based relay - std::set setInventoryKnown; + mruset setInventoryKnown; std::vector vInventoryToSend; CCriticalSection cs_inventory; std::multimap mapAskFor; - // publish and subscription - std::vector vfSubscribe; - - CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false) + CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : vSend(SER_NETWORK, MIN_PROTO_VERSION), vRecv(SER_NETWORK, MIN_PROTO_VERSION) { 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(); @@ -183,8 +223,10 @@ public: nHeaderStart = -1; nMessageStart = -1; addr = addrIn; + addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn; nVersion = 0; strSubVer = ""; + fOneShot = false; fClient = false; // set by version message fInbound = fInboundIn; fNetworkNode = false; @@ -196,12 +238,14 @@ public: pindexLastGetBlocksBegin = 0; hashLastGetBlocksEnd = 0; nStartingHeight = -1; + fStartSync = false; fGetAddr = false; - vfSubscribe.assign(256, false); nMisbehavior = 0; + hashCheckpointKnown = 0; + setInventoryKnown.max_size(SendBufferSize() / 1000); // Be shy and don't send version until we hear - if (!fInbound) + if (hSocket != INVALID_SOCKET && !fInbound) PushVersion(); } @@ -258,15 +302,19 @@ public: void AddInventoryKnown(const CInv& inv) { - CRITICAL_BLOCK(cs_inventory) + { + LOCK(cs_inventory); setInventoryKnown.insert(inv); + } } void PushInventory(const CInv& inv) { - CRITICAL_BLOCK(cs_inventory) + { + LOCK(cs_inventory); if (!setInventoryKnown.count(inv)) vInventoryToSend.push_back(inv); + } } void AskFor(const CInv& inv) @@ -274,7 +322,8 @@ public: // 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); + if (fDebugNet) + printf("askfor %s %"PRI64d" (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str()); // Make sure not to reuse time indexes to keep things in the same order int64 nNow = (GetTime() - 1) * 1000000; @@ -298,15 +347,13 @@ public: nHeaderStart = vSend.size(); vSend << CMessageHeader(pszCommand, 0); nMessageStart = vSend.size(); - if (fDebug) { - printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str()); + if (fDebug) printf("sending: %s ", pszCommand); - } } void AbortMessage() { - if (nHeaderStart == -1) + if (nHeaderStart < 0) return; vSend.resize(nHeaderStart); nHeaderStart = -1; @@ -326,22 +373,19 @@ public: return; } - if (nHeaderStart == -1) + if (nHeaderStart < 0) return; // Set the size unsigned int nSize = vSend.size() - nMessageStart; - memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize)); + memcpy((char*)&vSend[nHeaderStart] + CMessageHeader::MESSAGE_SIZE_OFFSET, &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)); - } + uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end()); + unsigned int nChecksum = 0; + memcpy(&nChecksum, &hash, sizeof(nChecksum)); + assert(nMessageStart - nHeaderStart >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum)); + memcpy((char*)&vSend[nHeaderStart] + CMessageHeader::CHECKSUM_OFFSET, &nChecksum, sizeof(nChecksum)); if (fDebug) { printf("(%d bytes)\n", nSize); @@ -354,7 +398,7 @@ public: void EndMessageAbortIfEmpty() { - if (nHeaderStart == -1) + if (nHeaderStart < 0) return; int nSize = vSend.size() - nMessageStart; if (nSize > 0) @@ -533,8 +577,10 @@ public: uint256 hashReply; RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); - CRITICAL_BLOCK(cs_mapRequests) + { + LOCK(cs_mapRequests); mapRequests[hashReply] = CRequestTracker(fn, param1); + } PushMessage(pszCommand, hashReply); } @@ -546,8 +592,10 @@ public: uint256 hashReply; RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); - CRITICAL_BLOCK(cs_mapRequests) + { + LOCK(cs_mapRequests); mapRequests[hashReply] = CRequestTracker(fn, param1); + } PushMessage(pszCommand, hashReply, a1); } @@ -559,8 +607,10 @@ public: uint256 hashReply; RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply)); - CRITICAL_BLOCK(cs_mapRequests) + { + LOCK(cs_mapRequests); mapRequests[hashReply] = CRequestTracker(fn, param1); + } PushMessage(pszCommand, hashReply, a1, a2); } @@ -592,107 +642,22 @@ public: static void ClearBanned(); // needed for unit testing static bool IsBanned(CNetAddr ip); bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot + void copyStats(CNodeStats &stats); }; - - - - - - - - - inline void RelayInventory(const CInv& inv) { // Put on lists to offer to the other nodes - CRITICAL_BLOCK(cs_vNodes) + { + LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) pnode->PushInventory(inv); -} - -template -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); } +class CTransaction; +void RelayTransaction(const CTransaction& tx, const uint256& hash); +void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss); - - - - - -// -// Templates for the publish and subscription system. -// The object being published as T& obj needs to have: -// a set setSources member -// specializations of AdvertInsert and AdvertErase -// Currently implemented for CTable and CProduct. -// - -template -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 -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 -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