Remove half-implemented publish/subscribe system
[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     unsigned 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)
161     {
162         nServices = 0;
163         hSocket = hSocketIn;
164         vSend.SetType(SER_NETWORK);
165         vRecv.SetType(SER_NETWORK);
166         vSend.SetVersion(209);
167         vRecv.SetVersion(209);
168         nLastSend = 0;
169         nLastRecv = 0;
170         nLastSendEmpty = GetTime();
171         nTimeConnected = GetTime();
172         nHeaderStart = -1;
173         nMessageStart = -1;
174         addr = addrIn;
175         nVersion = 0;
176         strSubVer = "";
177         fClient = false; // set by version message
178         fInbound = fInboundIn;
179         fNetworkNode = false;
180         fSuccessfullyConnected = false;
181         fDisconnect = false;
182         nRefCount = 0;
183         nReleaseTime = 0;
184         hashContinue = 0;
185         pindexLastGetBlocksBegin = 0;
186         hashLastGetBlocksEnd = 0;
187         nStartingHeight = -1;
188         fGetAddr = false;
189         nMisbehavior = 0;
190         setInventoryKnown.max_size(SendBufferSize() / 1000);
191
192         // Be shy and don't send version until we hear
193         if (!fInbound)
194             PushVersion();
195     }
196
197     ~CNode()
198     {
199         if (hSocket != INVALID_SOCKET)
200         {
201             closesocket(hSocket);
202             hSocket = INVALID_SOCKET;
203         }
204     }
205
206 private:
207     CNode(const CNode&);
208     void operator=(const CNode&);
209 public:
210
211
212     int GetRefCount()
213     {
214         return std::max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0);
215     }
216
217     CNode* AddRef(int64 nTimeout=0)
218     {
219         if (nTimeout != 0)
220             nReleaseTime = std::max(nReleaseTime, GetTime() + nTimeout);
221         else
222             nRefCount++;
223         return this;
224     }
225
226     void Release()
227     {
228         nRefCount--;
229     }
230
231
232
233     void AddAddressKnown(const CAddress& addr)
234     {
235         setAddrKnown.insert(addr);
236     }
237
238     void PushAddress(const CAddress& addr)
239     {
240         // Known checking here is only to save space from duplicates.
241         // SendMessages will filter it again for knowns that were added
242         // after addresses were pushed.
243         if (addr.IsValid() && !setAddrKnown.count(addr))
244             vAddrToSend.push_back(addr);
245     }
246
247
248     void AddInventoryKnown(const CInv& inv)
249     {
250         CRITICAL_BLOCK(cs_inventory)
251             setInventoryKnown.insert(inv);
252     }
253
254     void PushInventory(const CInv& inv)
255     {
256         CRITICAL_BLOCK(cs_inventory)
257             if (!setInventoryKnown.count(inv))
258                 vInventoryToSend.push_back(inv);
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 == -1)
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 == -1)
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 == -1)
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         CRITICAL_BLOCK(cs_mapRequests)
523             mapRequests[hashReply] = CRequestTracker(fn, param1);
524
525         PushMessage(pszCommand, hashReply);
526     }
527
528     template<typename T1>
529     void PushRequest(const char* pszCommand, const T1& a1,
530                      void (*fn)(void*, CDataStream&), void* param1)
531     {
532         uint256 hashReply;
533         RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
534
535         CRITICAL_BLOCK(cs_mapRequests)
536             mapRequests[hashReply] = CRequestTracker(fn, param1);
537
538         PushMessage(pszCommand, hashReply, a1);
539     }
540
541     template<typename T1, typename T2>
542     void PushRequest(const char* pszCommand, const T1& a1, const T2& a2,
543                      void (*fn)(void*, CDataStream&), void* param1)
544     {
545         uint256 hashReply;
546         RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
547
548         CRITICAL_BLOCK(cs_mapRequests)
549             mapRequests[hashReply] = CRequestTracker(fn, param1);
550
551         PushMessage(pszCommand, hashReply, a1, a2);
552     }
553
554
555
556     void PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd);
557     bool IsSubscribed(unsigned int nChannel);
558     void Subscribe(unsigned int nChannel, unsigned int nHops=0);
559     void CancelSubscribe(unsigned int nChannel);
560     void CloseSocketDisconnect();
561     void Cleanup();
562
563
564     // Denial-of-service detection/prevention
565     // The idea is to detect peers that are behaving
566     // badly and disconnect/ban them, but do it in a
567     // one-coding-mistake-won't-shatter-the-entire-network
568     // way.
569     // IMPORTANT:  There should be nothing I can give a
570     // node that it will forward on that will make that
571     // node's peers drop it. If there is, an attacker
572     // can isolate a node and/or try to split the network.
573     // Dropping a node for sending stuff that is invalid
574     // now but might be valid in a later version is also
575     // dangerous, because it can cause a network split
576     // between nodes running old code and nodes running
577     // new code.
578     static void ClearBanned(); // needed for unit testing
579     static bool IsBanned(CNetAddr ip);
580     bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot
581 };
582
583
584
585
586
587
588
589
590
591
592 inline void RelayInventory(const CInv& inv)
593 {
594     // Put on lists to offer to the other nodes
595     CRITICAL_BLOCK(cs_vNodes)
596         BOOST_FOREACH(CNode* pnode, vNodes)
597             pnode->PushInventory(inv);
598 }
599
600 template<typename T>
601 void RelayMessage(const CInv& inv, const T& a)
602 {
603     CDataStream ss(SER_NETWORK);
604     ss.reserve(10000);
605     ss << a;
606     RelayMessage(inv, ss);
607 }
608
609 template<>
610 inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
611 {
612     CRITICAL_BLOCK(cs_mapRelay)
613     {
614         // Expire old relay messages
615         while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
616         {
617             mapRelay.erase(vRelayExpiration.front().second);
618             vRelayExpiration.pop_front();
619         }
620
621         // Save original serialized message so newer versions are preserved
622         mapRelay[inv] = ss;
623         vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
624     }
625
626     RelayInventory(inv);
627 }
628
629
630 #endif