Initial commit of NovaCoin changes
[novacoin.git] / src / net.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Copyright (c) 2012 The PPCoin developers
4 // Copyright (c) 2012-2013 The NovaCoin developers
5 // Distributed under the MIT/X11 software license, see the accompanying
6 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 #ifndef BITCOIN_NET_H
8 #define BITCOIN_NET_H
9
10 #include <deque>
11 #include <boost/array.hpp>
12 #include <boost/foreach.hpp>
13 #include <openssl/rand.h>
14
15 #ifndef WIN32
16 #include <arpa/inet.h>
17 #endif
18
19 #include "mruset.h"
20 #include "netbase.h"
21 #include "protocol.h"
22 #include "addrman.h"
23
24 class CAddrDB;
25 class CRequestTracker;
26 class CNode;
27 class CBlockIndex;
28 extern int nBestHeight;
29
30
31
32 inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer", 10*1000); }
33 inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); }
34
35 bool RecvLine(SOCKET hSocket, std::string& strLine);
36 bool GetMyExternalIP(CNetAddr& ipRet);
37 void AddressCurrentlyConnected(const CService& addr);
38 CNode* FindNode(const CNetAddr& ip);
39 CNode* FindNode(const CService& ip);
40 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
41 void MapPort(bool fMapPort);
42 bool BindListenPort(std::string& strError=REF(std::string()));
43 void StartNode(void* parg);
44 bool StopNode();
45
46 enum
47 {
48     MSG_TX = 1,
49     MSG_BLOCK,
50 };
51
52 class CRequestTracker
53 {
54 public:
55     void (*fn)(void*, CDataStream&);
56     void* param1;
57
58     explicit CRequestTracker(void (*fnIn)(void*, CDataStream&)=NULL, void* param1In=NULL)
59     {
60         fn = fnIn;
61         param1 = param1In;
62     }
63
64     bool IsNull()
65     {
66         return fn == NULL;
67     }
68 };
69
70
71 /** Thread types */
72 enum threadId
73 {
74     THREAD_SOCKETHANDLER,
75     THREAD_OPENCONNECTIONS,
76     THREAD_MESSAGEHANDLER,
77     THREAD_MINER,
78     THREAD_RPCSERVER,
79     THREAD_UPNP,
80     THREAD_DNSSEED,
81     THREAD_ADDEDCONNECTIONS,
82     THREAD_DUMPADDRESS,
83     THREAD_MINTER,
84
85     THREAD_MAX
86 };
87
88 extern bool fClient;
89 extern bool fAllowDNS;
90 extern uint64 nLocalServices;
91 extern CAddress addrLocalHost;
92 extern CAddress addrSeenByPeer;
93 extern uint64 nLocalHostNonce;
94 extern boost::array<int, THREAD_MAX> vnThreadsRunning;
95 extern CAddrMan addrman;
96
97 extern std::vector<CNode*> vNodes;
98 extern CCriticalSection cs_vNodes;
99 extern std::map<CInv, CDataStream> mapRelay;
100 extern std::deque<std::pair<int64, CInv> > vRelayExpiration;
101 extern CCriticalSection cs_mapRelay;
102 extern std::map<CInv, int64> mapAlreadyAskedFor;
103
104
105
106
107
108
109 /** Information about a peer */
110 class CNode
111 {
112 public:
113     // socket
114     uint64 nServices;
115     SOCKET hSocket;
116     CDataStream vSend;
117     CDataStream vRecv;
118     CCriticalSection cs_vSend;
119     CCriticalSection cs_vRecv;
120     int64 nLastSend;
121     int64 nLastRecv;
122     int64 nLastSendEmpty;
123     int64 nTimeConnected;
124     int nHeaderStart;
125     unsigned int nMessageStart;
126     CAddress addr;
127     int nVersion;
128     std::string strSubVer;
129     bool fClient;
130     bool fInbound;
131     bool fNetworkNode;
132     bool fSuccessfullyConnected;
133     bool fDisconnect;
134     bool fHasGrant; // whether to call semOutbound.post() at disconnect
135 protected:
136     int nRefCount;
137
138     // Denial-of-service detection/prevention
139     // Key is ip address, value is banned-until-time
140     static std::map<CNetAddr, int64> setBanned;
141     static CCriticalSection cs_setBanned;
142     int nMisbehavior;
143
144 public:
145     int64 nReleaseTime;
146     std::map<uint256, CRequestTracker> mapRequests;
147     CCriticalSection cs_mapRequests;
148     uint256 hashContinue;
149     CBlockIndex* pindexLastGetBlocksBegin;
150     uint256 hashLastGetBlocksEnd;
151     int nStartingHeight;
152
153     // flood relay
154     std::vector<CAddress> vAddrToSend;
155     std::set<CAddress> setAddrKnown;
156     bool fGetAddr;
157     std::set<uint256> setKnown;
158     uint256 hashCheckpointKnown; // ppcoin: known sent sync-checkpoint
159
160     // inventory based relay
161     mruset<CInv> setInventoryKnown;
162     std::vector<CInv> vInventoryToSend;
163     CCriticalSection cs_inventory;
164     std::multimap<int64, CInv> mapAskFor;
165
166     CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false) : vSend(SER_NETWORK, MIN_PROTO_VERSION), vRecv(SER_NETWORK, MIN_PROTO_VERSION)
167     {
168         nServices = 0;
169         hSocket = hSocketIn;
170         nLastSend = 0;
171         nLastRecv = 0;
172         nLastSendEmpty = GetTime();
173         nTimeConnected = GetTime();
174         nHeaderStart = -1;
175         nMessageStart = -1;
176         addr = addrIn;
177         nVersion = 0;
178         strSubVer = "";
179         fClient = false; // set by version message
180         fHasGrant = false;
181         fInbound = fInboundIn;
182         fNetworkNode = false;
183         fSuccessfullyConnected = false;
184         fDisconnect = false;
185         nRefCount = 0;
186         nReleaseTime = 0;
187         hashContinue = 0;
188         pindexLastGetBlocksBegin = 0;
189         hashLastGetBlocksEnd = 0;
190         nStartingHeight = -1;
191         fGetAddr = false;
192         nMisbehavior = 0;
193         hashCheckpointKnown = 0;
194         setInventoryKnown.max_size(SendBufferSize() / 1000);
195
196         // Be shy and don't send version until we hear
197         if (!fInbound)
198             PushVersion();
199     }
200
201     ~CNode()
202     {
203         if (hSocket != INVALID_SOCKET)
204         {
205             closesocket(hSocket);
206             hSocket = INVALID_SOCKET;
207         }
208     }
209
210 private:
211     CNode(const CNode&);
212     void operator=(const CNode&);
213 public:
214
215
216     int GetRefCount()
217     {
218         return std::max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0);
219     }
220
221     CNode* AddRef(int64 nTimeout=0)
222     {
223         if (nTimeout != 0)
224             nReleaseTime = std::max(nReleaseTime, GetTime() + nTimeout);
225         else
226             nRefCount++;
227         return this;
228     }
229
230     void Release()
231     {
232         nRefCount--;
233     }
234
235
236
237     void AddAddressKnown(const CAddress& addr)
238     {
239         setAddrKnown.insert(addr);
240     }
241
242     void PushAddress(const CAddress& addr)
243     {
244         // Known checking here is only to save space from duplicates.
245         // SendMessages will filter it again for knowns that were added
246         // after addresses were pushed.
247         if (addr.IsValid() && !setAddrKnown.count(addr))
248             vAddrToSend.push_back(addr);
249     }
250
251
252     void AddInventoryKnown(const CInv& inv)
253     {
254         {
255             LOCK(cs_inventory);
256             setInventoryKnown.insert(inv);
257         }
258     }
259
260     void PushInventory(const CInv& inv)
261     {
262         {
263             LOCK(cs_inventory);
264             if (!setInventoryKnown.count(inv))
265                 vInventoryToSend.push_back(inv);
266         }
267     }
268
269     void AskFor(const CInv& inv)
270     {
271         // We're using mapAskFor as a priority queue,
272         // the key is the earliest time the request can be sent
273         int64& nRequestTime = mapAlreadyAskedFor[inv];
274         printf("askfor %s   %"PRI64d"\n", inv.ToString().c_str(), nRequestTime);
275
276         // Make sure not to reuse time indexes to keep things in the same order
277         int64 nNow = (GetTime() - 1) * 1000000;
278         static int64 nLastTime;
279         ++nLastTime;
280         nNow = std::max(nNow, nLastTime);
281         nLastTime = nNow;
282
283         // Each retry is 2 minutes after the last
284         nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
285         mapAskFor.insert(std::make_pair(nRequestTime, inv));
286     }
287
288
289
290     void BeginMessage(const char* pszCommand)
291     {
292         ENTER_CRITICAL_SECTION(cs_vSend);
293         if (nHeaderStart != -1)
294             AbortMessage();
295         nHeaderStart = vSend.size();
296         vSend << CMessageHeader(pszCommand, 0);
297         nMessageStart = vSend.size();
298         if (fDebug) {
299             printf("%s ", DateTimeStrFormat(GetTime()).c_str());
300             printf("sending: %s ", pszCommand);
301         }
302     }
303
304     void AbortMessage()
305     {
306         if (nHeaderStart < 0)
307             return;
308         vSend.resize(nHeaderStart);
309         nHeaderStart = -1;
310         nMessageStart = -1;
311         LEAVE_CRITICAL_SECTION(cs_vSend);
312
313         if (fDebug)
314             printf("(aborted)\n");
315     }
316
317     void EndMessage()
318     {
319         if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
320         {
321             printf("dropmessages DROPPING SEND MESSAGE\n");
322             AbortMessage();
323             return;
324         }
325
326         if (nHeaderStart < 0)
327             return;
328
329         // Set the size
330         unsigned int nSize = vSend.size() - nMessageStart;
331         memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
332
333         // Set the checksum
334         uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
335         unsigned int nChecksum = 0;
336         memcpy(&nChecksum, &hash, sizeof(nChecksum));
337         assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum));
338         memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum));
339
340         if (fDebug) {
341             printf("(%d bytes)\n", nSize);
342         }
343
344         nHeaderStart = -1;
345         nMessageStart = -1;
346         LEAVE_CRITICAL_SECTION(cs_vSend);
347     }
348
349     void EndMessageAbortIfEmpty()
350     {
351         if (nHeaderStart < 0)
352             return;
353         int nSize = vSend.size() - nMessageStart;
354         if (nSize > 0)
355             EndMessage();
356         else
357             AbortMessage();
358     }
359
360
361
362     void PushVersion();
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         {
531             LOCK(cs_mapRequests);
532             mapRequests[hashReply] = CRequestTracker(fn, param1);
533         }
534
535         PushMessage(pszCommand, hashReply);
536     }
537
538     template<typename T1>
539     void PushRequest(const char* pszCommand, const T1& a1,
540                      void (*fn)(void*, CDataStream&), void* param1)
541     {
542         uint256 hashReply;
543         RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
544
545         {
546             LOCK(cs_mapRequests);
547             mapRequests[hashReply] = CRequestTracker(fn, param1);
548         }
549
550         PushMessage(pszCommand, hashReply, a1);
551     }
552
553     template<typename T1, typename T2>
554     void PushRequest(const char* pszCommand, const T1& a1, const T2& a2,
555                      void (*fn)(void*, CDataStream&), void* param1)
556     {
557         uint256 hashReply;
558         RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
559
560         {
561             LOCK(cs_mapRequests);
562             mapRequests[hashReply] = CRequestTracker(fn, param1);
563         }
564
565         PushMessage(pszCommand, hashReply, a1, a2);
566     }
567
568
569
570     void PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd);
571     bool IsSubscribed(unsigned int nChannel);
572     void Subscribe(unsigned int nChannel, unsigned int nHops=0);
573     void CancelSubscribe(unsigned int nChannel);
574     void CloseSocketDisconnect();
575     void Cleanup();
576
577
578     // Denial-of-service detection/prevention
579     // The idea is to detect peers that are behaving
580     // badly and disconnect/ban them, but do it in a
581     // one-coding-mistake-won't-shatter-the-entire-network
582     // way.
583     // IMPORTANT:  There should be nothing I can give a
584     // node that it will forward on that will make that
585     // node's peers drop it. If there is, an attacker
586     // can isolate a node and/or try to split the network.
587     // Dropping a node for sending stuff that is invalid
588     // now but might be valid in a later version is also
589     // dangerous, because it can cause a network split
590     // between nodes running old code and nodes running
591     // new code.
592     static void ClearBanned(); // needed for unit testing
593     static bool IsBanned(CNetAddr ip);
594     bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot
595 };
596
597
598
599
600
601
602
603
604
605
606 inline void RelayInventory(const CInv& inv)
607 {
608     // Put on lists to offer to the other nodes
609     {
610         LOCK(cs_vNodes);
611         BOOST_FOREACH(CNode* pnode, vNodes)
612             pnode->PushInventory(inv);
613     }
614 }
615
616 template<typename T>
617 void RelayMessage(const CInv& inv, const T& a)
618 {
619     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
620     ss.reserve(10000);
621     ss << a;
622     RelayMessage(inv, ss);
623 }
624
625 template<>
626 inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
627 {
628     {
629         LOCK(cs_mapRelay);
630         // Expire old relay messages
631         while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
632         {
633             mapRelay.erase(vRelayExpiration.front().second);
634             vRelayExpiration.pop_front();
635         }
636
637         // Save original serialized message so newer versions are preserved
638         mapRelay.insert(std::make_pair(inv, ss));
639         vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
640     }
641
642     RelayInventory(inv);
643 }
644
645
646 #endif