Macros for manual critical sections
[novacoin.git] / src / net.h
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 #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;
270         nNow = std::max(nNow, nLastTime);
271         nLastTime = nNow;
272
273         // Each retry is 2 minutes after the last
274         nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
275         mapAskFor.insert(std::make_pair(nRequestTime, inv));
276     }
277
278
279
280     void BeginMessage(const char* pszCommand)
281     {
282         ENTER_CRITICAL_SECTION(cs_vSend);
283         if (nHeaderStart != -1)
284             AbortMessage();
285         nHeaderStart = vSend.size();
286         vSend << CMessageHeader(pszCommand, 0);
287         nMessageStart = vSend.size();
288         if (fDebug) {
289             printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
290             printf("sending: %s ", pszCommand);
291         }
292     }
293
294     void AbortMessage()
295     {
296         if (nHeaderStart == -1)
297             return;
298         vSend.resize(nHeaderStart);
299         nHeaderStart = -1;
300         nMessageStart = -1;
301         LEAVE_CRITICAL_SECTION(cs_vSend);
302
303         if (fDebug)
304             printf("(aborted)\n");
305     }
306
307     void EndMessage()
308     {
309         if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
310         {
311             printf("dropmessages DROPPING SEND MESSAGE\n");
312             AbortMessage();
313             return;
314         }
315
316         if (nHeaderStart == -1)
317             return;
318
319         // Set the size
320         unsigned int nSize = vSend.size() - nMessageStart;
321         memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
322
323         // Set the checksum
324         if (vSend.GetVersion() >= 209)
325         {
326             uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
327             unsigned int nChecksum = 0;
328             memcpy(&nChecksum, &hash, sizeof(nChecksum));
329             assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum));
330             memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum));
331         }
332
333         if (fDebug) {
334             printf("(%d bytes)\n", nSize);
335         }
336
337         nHeaderStart = -1;
338         nMessageStart = -1;
339         LEAVE_CRITICAL_SECTION(cs_vSend);
340     }
341
342     void EndMessageAbortIfEmpty()
343     {
344         if (nHeaderStart == -1)
345             return;
346         int nSize = vSend.size() - nMessageStart;
347         if (nSize > 0)
348             EndMessage();
349         else
350             AbortMessage();
351     }
352
353
354
355     void PushVersion();
356
357
358     void PushMessage(const char* pszCommand)
359     {
360         try
361         {
362             BeginMessage(pszCommand);
363             EndMessage();
364         }
365         catch (...)
366         {
367             AbortMessage();
368             throw;
369         }
370     }
371
372     template<typename T1>
373     void PushMessage(const char* pszCommand, const T1& a1)
374     {
375         try
376         {
377             BeginMessage(pszCommand);
378             vSend << a1;
379             EndMessage();
380         }
381         catch (...)
382         {
383             AbortMessage();
384             throw;
385         }
386     }
387
388     template<typename T1, typename T2>
389     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2)
390     {
391         try
392         {
393             BeginMessage(pszCommand);
394             vSend << a1 << a2;
395             EndMessage();
396         }
397         catch (...)
398         {
399             AbortMessage();
400             throw;
401         }
402     }
403
404     template<typename T1, typename T2, typename T3>
405     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3)
406     {
407         try
408         {
409             BeginMessage(pszCommand);
410             vSend << a1 << a2 << a3;
411             EndMessage();
412         }
413         catch (...)
414         {
415             AbortMessage();
416             throw;
417         }
418     }
419
420     template<typename T1, typename T2, typename T3, typename T4>
421     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4)
422     {
423         try
424         {
425             BeginMessage(pszCommand);
426             vSend << a1 << a2 << a3 << a4;
427             EndMessage();
428         }
429         catch (...)
430         {
431             AbortMessage();
432             throw;
433         }
434     }
435
436     template<typename T1, typename T2, typename T3, typename T4, typename T5>
437     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5)
438     {
439         try
440         {
441             BeginMessage(pszCommand);
442             vSend << a1 << a2 << a3 << a4 << a5;
443             EndMessage();
444         }
445         catch (...)
446         {
447             AbortMessage();
448             throw;
449         }
450     }
451
452     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
453     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6)
454     {
455         try
456         {
457             BeginMessage(pszCommand);
458             vSend << a1 << a2 << a3 << a4 << a5 << a6;
459             EndMessage();
460         }
461         catch (...)
462         {
463             AbortMessage();
464             throw;
465         }
466     }
467
468     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
469     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)
470     {
471         try
472         {
473             BeginMessage(pszCommand);
474             vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7;
475             EndMessage();
476         }
477         catch (...)
478         {
479             AbortMessage();
480             throw;
481         }
482     }
483
484     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
485     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)
486     {
487         try
488         {
489             BeginMessage(pszCommand);
490             vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8;
491             EndMessage();
492         }
493         catch (...)
494         {
495             AbortMessage();
496             throw;
497         }
498     }
499
500     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
501     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)
502     {
503         try
504         {
505             BeginMessage(pszCommand);
506             vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9;
507             EndMessage();
508         }
509         catch (...)
510         {
511             AbortMessage();
512             throw;
513         }
514     }
515
516
517     void PushRequest(const char* pszCommand,
518                      void (*fn)(void*, CDataStream&), void* param1)
519     {
520         uint256 hashReply;
521         RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
522
523         CRITICAL_BLOCK(cs_mapRequests)
524             mapRequests[hashReply] = CRequestTracker(fn, param1);
525
526         PushMessage(pszCommand, hashReply);
527     }
528
529     template<typename T1>
530     void PushRequest(const char* pszCommand, const T1& a1,
531                      void (*fn)(void*, CDataStream&), void* param1)
532     {
533         uint256 hashReply;
534         RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
535
536         CRITICAL_BLOCK(cs_mapRequests)
537             mapRequests[hashReply] = CRequestTracker(fn, param1);
538
539         PushMessage(pszCommand, hashReply, a1);
540     }
541
542     template<typename T1, typename T2>
543     void PushRequest(const char* pszCommand, const T1& a1, const T2& a2,
544                      void (*fn)(void*, CDataStream&), void* param1)
545     {
546         uint256 hashReply;
547         RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
548
549         CRITICAL_BLOCK(cs_mapRequests)
550             mapRequests[hashReply] = CRequestTracker(fn, param1);
551
552         PushMessage(pszCommand, hashReply, a1, a2);
553     }
554
555
556
557     void PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd);
558     bool IsSubscribed(unsigned int nChannel);
559     void Subscribe(unsigned int nChannel, unsigned int nHops=0);
560     void CancelSubscribe(unsigned int nChannel);
561     void CloseSocketDisconnect();
562     void Cleanup();
563
564
565     // Denial-of-service detection/prevention
566     // The idea is to detect peers that are behaving
567     // badly and disconnect/ban them, but do it in a
568     // one-coding-mistake-won't-shatter-the-entire-network
569     // way.
570     // IMPORTANT:  There should be nothing I can give a
571     // node that it will forward on that will make that
572     // node's peers drop it. If there is, an attacker
573     // can isolate a node and/or try to split the network.
574     // Dropping a node for sending stuff that is invalid
575     // now but might be valid in a later version is also
576     // dangerous, because it can cause a network split
577     // between nodes running old code and nodes running
578     // new code.
579     static void ClearBanned(); // needed for unit testing
580     static bool IsBanned(CNetAddr ip);
581     bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot
582 };
583
584
585
586
587
588
589
590
591
592
593 inline void RelayInventory(const CInv& inv)
594 {
595     // Put on lists to offer to the other nodes
596     CRITICAL_BLOCK(cs_vNodes)
597         BOOST_FOREACH(CNode* pnode, vNodes)
598             pnode->PushInventory(inv);
599 }
600
601 template<typename T>
602 void RelayMessage(const CInv& inv, const T& a)
603 {
604     CDataStream ss(SER_NETWORK);
605     ss.reserve(10000);
606     ss << a;
607     RelayMessage(inv, ss);
608 }
609
610 template<>
611 inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
612 {
613     CRITICAL_BLOCK(cs_mapRelay)
614     {
615         // Expire old relay messages
616         while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
617         {
618             mapRelay.erase(vRelayExpiration.front().second);
619             vRelayExpiration.pop_front();
620         }
621
622         // Save original serialized message so newer versions are preserved
623         mapRelay[inv] = ss;
624         vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
625     }
626
627     RelayInventory(inv);
628 }
629
630
631
632
633
634
635
636
637 //
638 // Templates for the publish and subscription system.
639 // The object being published as T& obj needs to have:
640 //   a set<unsigned int> setSources member
641 //   specializations of AdvertInsert and AdvertErase
642 // Currently implemented for CTable and CProduct.
643 //
644
645 template<typename T>
646 void AdvertStartPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
647 {
648     // Add to sources
649     obj.setSources.insert(pfrom->addr.ip);
650
651     if (!AdvertInsert(obj))
652         return;
653
654     // Relay
655     CRITICAL_BLOCK(cs_vNodes)
656         BOOST_FOREACH(CNode* pnode, vNodes)
657             if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
658                 pnode->PushMessage("publish", nChannel, nHops, obj);
659 }
660
661 template<typename T>
662 void AdvertStopPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
663 {
664     uint256 hash = obj.GetHash();
665
666     CRITICAL_BLOCK(cs_vNodes)
667         BOOST_FOREACH(CNode* pnode, vNodes)
668             if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
669                 pnode->PushMessage("pub-cancel", nChannel, nHops, hash);
670
671     AdvertErase(obj);
672 }
673
674 template<typename T>
675 void AdvertRemoveSource(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
676 {
677     // Remove a source
678     obj.setSources.erase(pfrom->addr.ip);
679
680     // If no longer supported by any sources, cancel it
681     if (obj.setSources.empty())
682         AdvertStopPublish(pfrom, nChannel, nHops, obj);
683 }
684
685 #endif