1// Copyright (c) 2009-2010 Satoshi Nakamoto
  2// Copyright (c) 2009-2012 The Bitcoin developers
  3// Distributed under the MIT/X11 software license, see the accompanying
  4// file license.txt or http://www.opensource.org/licenses/mit-license.php.
  5#ifndef BITCOIN_NET_H
  6#define BITCOIN_NET_H
  7
  8#include <deque>
  9#include <boost/array.hpp>
 10#include <boost/foreach.hpp>
 11#include <openssl/rand.h>
 12
 13#include "protocol.h"
 14
 15class CAddrDB;
 16class CRequestTracker;
 17class CNode;
 18class CBlockIndex;
 19extern int nBestHeight;
 20extern int nConnectTimeout;
 21
 22
 23
 24inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer", 10*1000); }
 25inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); }
 26static const unsigned int PUBLISH_HOPS = 5;
 27
 28bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout=nConnectTimeout);
 29bool Lookup(const char *pszName, std::vector<CAddress>& vaddr, int nServices, int nMaxSolutions, int portDefault = 0, bool fAllowPort = false);
 30bool Lookup(const char *pszName, CAddress& addr, int nServices, int portDefault = 0, bool fAllowPort = false);
 31bool AddAddress(CAddress addr, int64 nTimePenalty=0, CAddrDB *pAddrDB=NULL);
 32void AddressCurrentlyConnected(const CAddress& addr);
 33CNode* FindNode(unsigned int ip);
 34CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
 35void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
 36bool AnySubscribed(unsigned int nChannel);
 37void MapPort(bool fMapPort);
 38bool BindListenPort(std::string& strError=REF(std::string()));
 39void StartNode(void* parg);
 40bool StopNode();
 41
 42enum
 43{
 44    MSG_TX = 1,
 45    MSG_BLOCK,
 46};
 47
 48class CRequestTracker
 49{
 50public:
 51    void (*fn)(void*, CDataStream&);
 52    void* param1;
 53
 54    explicit CRequestTracker(void (*fnIn)(void*, CDataStream&)=NULL, void* param1In=NULL)
 55    {
 56        fn = fnIn;
 57        param1 = param1In;
 58    }
 59
 60    bool IsNull()
 61    {
 62        return fn == NULL;
 63    }
 64};
 65
 66
 67
 68
 69
 70extern bool fClient;
 71extern bool fAllowDNS;
 72extern uint64 nLocalServices;
 73extern CAddress addrLocalHost;
 74extern uint64 nLocalHostNonce;
 75extern boost::array<int, 10> vnThreadsRunning;
 76
 77extern std::vector<CNode*> vNodes;
 78extern CCriticalSection cs_vNodes;
 79extern std::map<std::vector<unsigned char>, CAddress> mapAddresses;
 80extern CCriticalSection cs_mapAddresses;
 81extern std::map<CInv, CDataStream> mapRelay;
 82extern std::deque<std::pair<int64, CInv> > vRelayExpiration;
 83extern CCriticalSection cs_mapRelay;
 84extern std::map<CInv, int64> mapAlreadyAskedFor;
 85
 86// Settings
 87extern int fUseProxy;
 88extern CAddress addrProxy;
 89
 90
 91
 92
 93
 94
 95class CNode
 96{
 97public:
 98    // socket
 99    uint64 nServices;
100    SOCKET hSocket;
101    CDataStream vSend;
102    CDataStream vRecv;
103    CCriticalSection cs_vSend;
104    CCriticalSection cs_vRecv;
105    int64 nLastSend;
106    int64 nLastRecv;
107    int64 nLastSendEmpty;
108    int64 nTimeConnected;
109    unsigned int nHeaderStart;
110    unsigned int nMessageStart;
111    CAddress addr;
112    int nVersion;
113    std::string strSubVer;
114    bool fClient;
115    bool fInbound;
116    bool fNetworkNode;
117    bool fSuccessfullyConnected;
118    bool fDisconnect;
119protected:
120    int nRefCount;
121
122    // Denial-of-service detection/prevention
123    // Key is ip address, value is banned-until-time
124    static std::map<unsigned int, int64> setBanned;
125    static CCriticalSection cs_setBanned;
126    int nMisbehavior;
127
128public:
129    int64 nReleaseTime;
130    std::map<uint256, CRequestTracker> mapRequests;
131    CCriticalSection cs_mapRequests;
132    uint256 hashContinue;
133    int nStartingHeight;
134
135    // flood relay
136    std::vector<CAddress> vAddrToSend;
137    std::set<CAddress> setAddrKnown;
138    bool fGetAddr;
139    std::set<uint256> setKnown;
140
141    // inventory based relay
142    std::set<CInv> setInventoryKnown;
143    std::vector<CInv> vInventoryToSend;
144    CCriticalSection cs_inventory;
145    std::multimap<int64, CInv> mapAskFor;
146
147    // publish and subscription
148    std::vector<char> vfSubscribe;
149
150    CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false)
151    {
152        nServices = 0;
153        hSocket = hSocketIn;
154        vSend.SetType(SER_NETWORK);
155        vSend.SetVersion(0);
156        vRecv.SetType(SER_NETWORK);
157        vRecv.SetVersion(0);
158        // Version 0.2 obsoletes 20 Feb 2012
159        if (GetTime() > 1329696000)
160        {
161            vSend.SetVersion(209);
162            vRecv.SetVersion(209);
163        }
164        nLastSend = 0;
165        nLastRecv = 0;
166        nLastSendEmpty = GetTime();
167        nTimeConnected = GetTime();
168        nHeaderStart = -1;
169        nMessageStart = -1;
170        addr = addrIn;
171        nVersion = 0;
172        strSubVer = "";
173        fClient = false; // set by version message
174        fInbound = fInboundIn;
175        fNetworkNode = false;
176        fSuccessfullyConnected = false;
177        fDisconnect = false;
178        nRefCount = 0;
179        nReleaseTime = 0;
180        hashContinue = 0;
181        nStartingHeight = -1;
182        fGetAddr = false;
183        vfSubscribe.assign(256, false);
184        nMisbehavior = 0;
185
186        // Be shy and don't send version until we hear
187        if (!fInbound)
188            PushVersion();
189    }
190
191    ~CNode()
192    {
193        if (hSocket != INVALID_SOCKET)
194        {
195            closesocket(hSocket);
196            hSocket = INVALID_SOCKET;
197        }
198    }
199
200private:
201    CNode(const CNode&);
202    void operator=(const CNode&);
203public:
204
205
206    int GetRefCount()
207    {
208        return std::max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0);
209    }
210
211    CNode* AddRef(int64 nTimeout=0)
212    {
213        if (nTimeout != 0)
214            nReleaseTime = std::max(nReleaseTime, GetTime() + nTimeout);
215        else
216            nRefCount++;
217        return this;
218    }
219
220    void Release()
221    {
222        nRefCount--;
223    }
224
225
226
227    void AddAddressKnown(const CAddress& addr)
228    {
229        setAddrKnown.insert(addr);
230    }
231
232    void PushAddress(const CAddress& addr)
233    {
234        // Known checking here is only to save space from duplicates.
235        // SendMessages will filter it again for knowns that were added
236        // after addresses were pushed.
237        if (addr.IsValid() && !setAddrKnown.count(addr))
238            vAddrToSend.push_back(addr);
239    }
240
241
242    void AddInventoryKnown(const CInv& inv)
243    {
244        CRITICAL_BLOCK(cs_inventory)
245            setInventoryKnown.insert(inv);
246    }
247
248    void PushInventory(const CInv& inv)
249    {
250        CRITICAL_BLOCK(cs_inventory)
251            if (!setInventoryKnown.count(inv))
252                vInventoryToSend.push_back(inv);
253    }
254
255    void AskFor(const CInv& inv)
256    {
257        // We're using mapAskFor as a priority queue,
258        // the key is the earliest time the request can be sent
259        int64& nRequestTime = mapAlreadyAskedFor[inv];
260        printf("askfor %s   %"PRI64d"\n", inv.ToString().c_str(), nRequestTime);
261
262        // Make sure not to reuse time indexes to keep things in the same order
263        int64 nNow = (GetTime() - 1) * 1000000;
264        static int64 nLastTime;
265        ++nLastTime;
266        nNow = std::max(nNow, nLastTime);
267        nLastTime = nNow;
268
269        // Each retry is 2 minutes after the last
270        nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
271        mapAskFor.insert(std::make_pair(nRequestTime, inv));
272    }
273
274
275
276    void BeginMessage(const char* pszCommand)
277    {
278        ENTER_CRITICAL_SECTION(cs_vSend);
279        if (nHeaderStart != -1)
280            AbortMessage();
281        nHeaderStart = vSend.size();
282        vSend << CMessageHeader(pszCommand, 0);
283        nMessageStart = vSend.size();
284        if (fDebug) {
285            printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
286            printf("sending: %s ", pszCommand);
287        }
288    }
289
290    void AbortMessage()
291    {
292        if (nHeaderStart == -1)
293            return;
294        vSend.resize(nHeaderStart);
295        nHeaderStart = -1;
296        nMessageStart = -1;
297        LEAVE_CRITICAL_SECTION(cs_vSend);
298
299        if (fDebug)
300            printf("(aborted)\n");
301    }
302
303    void EndMessage()
304    {
305        if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
306        {
307            printf("dropmessages DROPPING SEND MESSAGE\n");
308            AbortMessage();
309            return;
310        }
311
312        if (nHeaderStart == -1)
313            return;
314
315        // Set the size
316        unsigned int nSize = vSend.size() - nMessageStart;
317        memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
318
319        // Set the checksum
320        if (vSend.GetVersion() >= 209)
321        {
322            uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
323            unsigned int nChecksum = 0;
324            memcpy(&nChecksum, &hash, sizeof(nChecksum));
325            assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum));
326            memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum));
327        }
328
329        if (fDebug) {
330            printf("(%d bytes)\n", nSize);
331        }
332
333        nHeaderStart = -1;
334        nMessageStart = -1;
335        LEAVE_CRITICAL_SECTION(cs_vSend);
336    }
337
338    void EndMessageAbortIfEmpty()
339    {
340        if (nHeaderStart == -1)
341            return;
342        int nSize = vSend.size() - nMessageStart;
343        if (nSize > 0)
344            EndMessage();
345        else
346            AbortMessage();
347    }
348
349
350
351    void PushVersion()
352    {
353        /// when NTP implemented, change to just nTime = GetAdjustedTime()
354        int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
355        CAddress addrYou = (fUseProxy ? CAddress("0.0.0.0") : addr);
356        CAddress addrMe = (fUseProxy || !addrLocalHost.IsRoutable() ? CAddress("0.0.0.0") : addrLocalHost);
357        RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
358        PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe,
359                    nLocalHostNonce, FormatSubVersion(CLIENT_NAME, VERSION), nBestHeight);
360    }
361
362
363
364
365    void PushMessage(const char* pszCommand)
366    {
367        try
368        {
369            BeginMessage(pszCommand);
370            EndMessage();
371        }
372        catch (...)
373        {
374            AbortMessage();
375            throw;
376        }
377    }
378
379    template<typename T1>
380    void PushMessage(const char* pszCommand, const T1& a1)
381    {
382        try
383        {
384            BeginMessage(pszCommand);
385            vSend << a1;
386            EndMessage();
387        }
388        catch (...)
389        {
390            AbortMessage();
391            throw;
392        }
393    }
394
395    template<typename T1, typename T2>
396    void PushMessage(const char* pszCommand, const T1& a1, const T2& a2)
397    {
398        try
399        {
400            BeginMessage(pszCommand);
401            vSend << a1 << a2;
402            EndMessage();
403        }
404        catch (...)
405        {
406            AbortMessage();
407            throw;
408        }
409    }
410
411    template<typename T1, typename T2, typename T3>
412    void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3)
413    {
414        try
415        {
416            BeginMessage(pszCommand);
417            vSend << a1 << a2 << a3;
418            EndMessage();
419        }
420        catch (...)
421        {
422            AbortMessage();
423            throw;
424        }
425    }
426
427    template<typename T1, typename T2, typename T3, typename T4>
428    void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4)
429    {
430        try
431        {
432            BeginMessage(pszCommand);
433            vSend << a1 << a2 << a3 << a4;
434            EndMessage();
435        }
436        catch (...)
437        {
438            AbortMessage();
439            throw;
440        }
441    }
442
443    template<typename T1, typename T2, typename T3, typename T4, typename T5>
444    void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5)
445    {
446        try
447        {
448            BeginMessage(pszCommand);
449            vSend << a1 << a2 << a3 << a4 << a5;
450            EndMessage();
451        }
452        catch (...)
453        {
454            AbortMessage();
455            throw;
456        }
457    }
458
459    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
460    void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6)
461    {
462        try
463        {
464            BeginMessage(pszCommand);
465            vSend << a1 << a2 << a3 << a4 << a5 << a6;
466            EndMessage();
467        }
468        catch (...)
469        {
470            AbortMessage();
471            throw;
472        }
473    }
474
475    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
476    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)
477    {
478        try
479        {
480            BeginMessage(pszCommand);
481            vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7;
482            EndMessage();
483        }
484        catch (...)
485        {
486            AbortMessage();
487            throw;
488        }
489    }
490
491    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
492    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)
493    {
494        try
495        {
496            BeginMessage(pszCommand);
497            vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8;
498            EndMessage();
499        }
500        catch (...)
501        {
502            AbortMessage();
503            throw;
504        }
505    }
506
507    template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
508    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)
509    {
510        try
511        {
512            BeginMessage(pszCommand);
513            vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9;
514            EndMessage();
515        }
516        catch (...)
517        {
518            AbortMessage();
519            throw;
520        }
521    }
522
523
524    void PushRequest(const char* pszCommand,
525                     void (*fn)(void*, CDataStream&), void* param1)
526    {
527        uint256 hashReply;
528        RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
529
530        CRITICAL_BLOCK(cs_mapRequests)
531            mapRequests[hashReply] = CRequestTracker(fn, param1);
532
533        PushMessage(pszCommand, hashReply);
534    }
535
536    template<typename T1>
537    void PushRequest(const char* pszCommand, const T1& a1,
538                     void (*fn)(void*, CDataStream&), void* param1)
539    {
540        uint256 hashReply;
541        RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
542
543        CRITICAL_BLOCK(cs_mapRequests)
544            mapRequests[hashReply] = CRequestTracker(fn, param1);
545
546        PushMessage(pszCommand, hashReply, a1);
547    }
548
549    template<typename T1, typename T2>
550    void PushRequest(const char* pszCommand, const T1& a1, const T2& a2,
551                     void (*fn)(void*, CDataStream&), void* param1)
552    {
553        uint256 hashReply;
554        RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
555
556        CRITICAL_BLOCK(cs_mapRequests)
557            mapRequests[hashReply] = CRequestTracker(fn, param1);
558
559        PushMessage(pszCommand, hashReply, a1, a2);
560    }
561
562
563
564    void PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd);
565    bool IsSubscribed(unsigned int nChannel);
566    void Subscribe(unsigned int nChannel, unsigned int nHops=0);
567    void CancelSubscribe(unsigned int nChannel);
568    void CloseSocketDisconnect();
569    void Cleanup();
570
571
572    // Denial-of-service detection/prevention
573    // The idea is to detect peers that are behaving
574    // badly and disconnect/ban them, but do it in a
575    // one-coding-mistake-won't-shatter-the-entire-network
576    // way.
577    // IMPORTANT:  There should be nothing I can give a
578    // node that it will forward on that will make that
579    // node's peers drop it. If there is, an attacker
580    // can isolate a node and/or try to split the network.
581    // Dropping a node for sending stuff that is invalid
582    // now but might be valid in a later version is also
583    // dangerous, because it can cause a network split
584    // between nodes running old code and nodes running
585    // new code.
586    static void ClearBanned(); // needed for unit testing
587    static bool IsBanned(unsigned int ip);
588    bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot
589};
590
591
592
593
594
595
596
597
598
599
600inline void RelayInventory(const CInv& inv)
601{
602    // Put on lists to offer to the other nodes
603    CRITICAL_BLOCK(cs_vNodes)
604        BOOST_FOREACH(CNode* pnode, vNodes)
605            pnode->PushInventory(inv);
606}
607
608template<typename T>
609void RelayMessage(const CInv& inv, const T& a)
610{
611    CDataStream ss(SER_NETWORK);
612    ss.reserve(10000);
613    ss << a;
614    RelayMessage(inv, ss);
615}
616
617template<>
618inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
619{
620    CRITICAL_BLOCK(cs_mapRelay)
621    {
622        // Expire old relay messages
623        while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
624        {
625            mapRelay.erase(vRelayExpiration.front().second);
626            vRelayExpiration.pop_front();
627        }
628
629        // Save original serialized message so newer versions are preserved
630        mapRelay[inv] = ss;
631        vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
632    }
633
634    RelayInventory(inv);
635}
636
637
638
639
640
641
642
643
644//
645// Templates for the publish and subscription system.
646// The object being published as T& obj needs to have:
647//   a set<unsigned int> setSources member
648//   specializations of AdvertInsert and AdvertErase
649// Currently implemented for CTable and CProduct.
650//
651
652template<typename T>
653void AdvertStartPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
654{
655    // Add to sources
656    obj.setSources.insert(pfrom->addr.ip);
657
658    if (!AdvertInsert(obj))
659        return;
660
661    // Relay
662    CRITICAL_BLOCK(cs_vNodes)
663        BOOST_FOREACH(CNode* pnode, vNodes)
664            if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
665                pnode->PushMessage("publish", nChannel, nHops, obj);
666}
667
668template<typename T>
669void AdvertStopPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
670{
671    uint256 hash = obj.GetHash();
672
673    CRITICAL_BLOCK(cs_vNodes)
674        BOOST_FOREACH(CNode* pnode, vNodes)
675            if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
676                pnode->PushMessage("pub-cancel", nChannel, nHops, hash);
677
678    AdvertErase(obj);
679}
680
681template<typename T>
682void AdvertRemoveSource(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
683{
684    // Remove a source
685    obj.setSources.erase(pfrom->addr.ip);
686
687    // If no longer supported by any sources, cancel it
688    if (obj.setSources.empty())
689        AdvertStopPublish(pfrom, nChannel, nHops, obj);
690}
691
692#endif