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