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