Fix #626: RecvLine wrong error message
[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 RecvLine(SOCKET hSocket, std::string& strLine);
33 bool GetMyExternalIP(CNetAddr& ipRet);
34 bool AddAddress(CAddress addr, int64 nTimePenalty=0, CAddrDB *pAddrDB=NULL);
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 AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
40 bool AnySubscribed(unsigned int nChannel);
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
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
83     THREAD_MAX
84 };
85
86 extern bool fClient;
87 extern bool fAllowDNS;
88 extern uint64 nLocalServices;
89 extern CAddress addrLocalHost;
90 extern uint64 nLocalHostNonce;
91 extern boost::array<int, THREAD_MAX> vnThreadsRunning;
92
93 extern std::vector<CNode*> vNodes;
94 extern CCriticalSection cs_vNodes;
95 extern std::map<std::vector<unsigned char>, CAddress> mapAddresses;
96 extern CCriticalSection cs_mapAddresses;
97 extern std::map<CInv, CDataStream> mapRelay;
98 extern std::deque<std::pair<int64, CInv> > vRelayExpiration;
99 extern CCriticalSection cs_mapRelay;
100 extern std::map<CInv, int64> mapAlreadyAskedFor;
101
102
103
104
105
106
107
108 class CNode
109 {
110 public:
111     // socket
112     uint64 nServices;
113     SOCKET hSocket;
114     CDataStream vSend;
115     CDataStream vRecv;
116     CCriticalSection cs_vSend;
117     CCriticalSection cs_vRecv;
118     int64 nLastSend;
119     int64 nLastRecv;
120     int64 nLastSendEmpty;
121     int64 nTimeConnected;
122     unsigned int nHeaderStart;
123     unsigned int nMessageStart;
124     CAddress addr;
125     int nVersion;
126     std::string strSubVer;
127     bool fClient;
128     bool fInbound;
129     bool fNetworkNode;
130     bool fSuccessfullyConnected;
131     bool fDisconnect;
132 protected:
133     int nRefCount;
134
135     // Denial-of-service detection/prevention
136     // Key is ip address, value is banned-until-time
137     static std::map<CNetAddr, int64> setBanned;
138     static CCriticalSection cs_setBanned;
139     int nMisbehavior;
140
141 public:
142     int64 nReleaseTime;
143     std::map<uint256, CRequestTracker> mapRequests;
144     CCriticalSection cs_mapRequests;
145     uint256 hashContinue;
146     CBlockIndex* pindexLastGetBlocksBegin;
147     uint256 hashLastGetBlocksEnd;
148     int nStartingHeight;
149
150     // flood relay
151     std::vector<CAddress> vAddrToSend;
152     std::set<CAddress> setAddrKnown;
153     bool fGetAddr;
154     std::set<uint256> setKnown;
155
156     // inventory based relay
157     std::set<CInv> setInventoryKnown;
158     std::vector<CInv> vInventoryToSend;
159     CCriticalSection cs_inventory;
160     std::multimap<int64, CInv> mapAskFor;
161
162     // publish and subscription
163     std::vector<char> vfSubscribe;
164
165     CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false)
166     {
167         nServices = 0;
168         hSocket = hSocketIn;
169         vSend.SetType(SER_NETWORK);
170         vSend.SetVersion(0);
171         vRecv.SetType(SER_NETWORK);
172         vRecv.SetVersion(0);
173         // Version 0.2 obsoletes 20 Feb 2012
174         if (GetTime() > 1329696000)
175         {
176             vSend.SetVersion(209);
177             vRecv.SetVersion(209);
178         }
179         nLastSend = 0;
180         nLastRecv = 0;
181         nLastSendEmpty = GetTime();
182         nTimeConnected = GetTime();
183         nHeaderStart = -1;
184         nMessageStart = -1;
185         addr = addrIn;
186         nVersion = 0;
187         strSubVer = "";
188         fClient = false; // set by version message
189         fInbound = fInboundIn;
190         fNetworkNode = false;
191         fSuccessfullyConnected = false;
192         fDisconnect = false;
193         nRefCount = 0;
194         nReleaseTime = 0;
195         hashContinue = 0;
196         pindexLastGetBlocksBegin = 0;
197         hashLastGetBlocksEnd = 0;
198         nStartingHeight = -1;
199         fGetAddr = false;
200         vfSubscribe.assign(256, false);
201         nMisbehavior = 0;
202
203         // Be shy and don't send version until we hear
204         if (!fInbound)
205             PushVersion();
206     }
207
208     ~CNode()
209     {
210         if (hSocket != INVALID_SOCKET)
211         {
212             closesocket(hSocket);
213             hSocket = INVALID_SOCKET;
214         }
215     }
216
217 private:
218     CNode(const CNode&);
219     void operator=(const CNode&);
220 public:
221
222
223     int GetRefCount()
224     {
225         return std::max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0);
226     }
227
228     CNode* AddRef(int64 nTimeout=0)
229     {
230         if (nTimeout != 0)
231             nReleaseTime = std::max(nReleaseTime, GetTime() + nTimeout);
232         else
233             nRefCount++;
234         return this;
235     }
236
237     void Release()
238     {
239         nRefCount--;
240     }
241
242
243
244     void AddAddressKnown(const CAddress& addr)
245     {
246         setAddrKnown.insert(addr);
247     }
248
249     void PushAddress(const CAddress& addr)
250     {
251         // Known checking here is only to save space from duplicates.
252         // SendMessages will filter it again for knowns that were added
253         // after addresses were pushed.
254         if (addr.IsValid() && !setAddrKnown.count(addr))
255             vAddrToSend.push_back(addr);
256     }
257
258
259     void AddInventoryKnown(const CInv& inv)
260     {
261         CRITICAL_BLOCK(cs_inventory)
262             setInventoryKnown.insert(inv);
263     }
264
265     void PushInventory(const CInv& inv)
266     {
267         CRITICAL_BLOCK(cs_inventory)
268             if (!setInventoryKnown.count(inv))
269                 vInventoryToSend.push_back(inv);
270     }
271
272     void AskFor(const CInv& inv)
273     {
274         // We're using mapAskFor as a priority queue,
275         // the key is the earliest time the request can be sent
276         int64& nRequestTime = mapAlreadyAskedFor[inv];
277         printf("askfor %s   %"PRI64d"\n", inv.ToString().c_str(), nRequestTime);
278
279         // Make sure not to reuse time indexes to keep things in the same order
280         int64 nNow = (GetTime() - 1) * 1000000;
281         static int64 nLastTime;
282         ++nLastTime;
283         nNow = std::max(nNow, nLastTime);
284         nLastTime = nNow;
285
286         // Each retry is 2 minutes after the last
287         nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
288         mapAskFor.insert(std::make_pair(nRequestTime, inv));
289     }
290
291
292
293     void BeginMessage(const char* pszCommand)
294     {
295         ENTER_CRITICAL_SECTION(cs_vSend);
296         if (nHeaderStart != -1)
297             AbortMessage();
298         nHeaderStart = vSend.size();
299         vSend << CMessageHeader(pszCommand, 0);
300         nMessageStart = vSend.size();
301         if (fDebug) {
302             printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
303             printf("sending: %s ", pszCommand);
304         }
305     }
306
307     void AbortMessage()
308     {
309         if (nHeaderStart == -1)
310             return;
311         vSend.resize(nHeaderStart);
312         nHeaderStart = -1;
313         nMessageStart = -1;
314         LEAVE_CRITICAL_SECTION(cs_vSend);
315
316         if (fDebug)
317             printf("(aborted)\n");
318     }
319
320     void EndMessage()
321     {
322         if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
323         {
324             printf("dropmessages DROPPING SEND MESSAGE\n");
325             AbortMessage();
326             return;
327         }
328
329         if (nHeaderStart == -1)
330             return;
331
332         // Set the size
333         unsigned int nSize = vSend.size() - nMessageStart;
334         memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
335
336         // Set the checksum
337         if (vSend.GetVersion() >= 209)
338         {
339             uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
340             unsigned int nChecksum = 0;
341             memcpy(&nChecksum, &hash, sizeof(nChecksum));
342             assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum));
343             memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum));
344         }
345
346         if (fDebug) {
347             printf("(%d bytes)\n", nSize);
348         }
349
350         nHeaderStart = -1;
351         nMessageStart = -1;
352         LEAVE_CRITICAL_SECTION(cs_vSend);
353     }
354
355     void EndMessageAbortIfEmpty()
356     {
357         if (nHeaderStart == -1)
358             return;
359         int nSize = vSend.size() - nMessageStart;
360         if (nSize > 0)
361             EndMessage();
362         else
363             AbortMessage();
364     }
365
366
367
368     void PushVersion();
369
370
371     void PushMessage(const char* pszCommand)
372     {
373         try
374         {
375             BeginMessage(pszCommand);
376             EndMessage();
377         }
378         catch (...)
379         {
380             AbortMessage();
381             throw;
382         }
383     }
384
385     template<typename T1>
386     void PushMessage(const char* pszCommand, const T1& a1)
387     {
388         try
389         {
390             BeginMessage(pszCommand);
391             vSend << a1;
392             EndMessage();
393         }
394         catch (...)
395         {
396             AbortMessage();
397             throw;
398         }
399     }
400
401     template<typename T1, typename T2>
402     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2)
403     {
404         try
405         {
406             BeginMessage(pszCommand);
407             vSend << a1 << a2;
408             EndMessage();
409         }
410         catch (...)
411         {
412             AbortMessage();
413             throw;
414         }
415     }
416
417     template<typename T1, typename T2, typename T3>
418     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3)
419     {
420         try
421         {
422             BeginMessage(pszCommand);
423             vSend << a1 << a2 << a3;
424             EndMessage();
425         }
426         catch (...)
427         {
428             AbortMessage();
429             throw;
430         }
431     }
432
433     template<typename T1, typename T2, typename T3, typename T4>
434     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4)
435     {
436         try
437         {
438             BeginMessage(pszCommand);
439             vSend << a1 << a2 << a3 << a4;
440             EndMessage();
441         }
442         catch (...)
443         {
444             AbortMessage();
445             throw;
446         }
447     }
448
449     template<typename T1, typename T2, typename T3, typename T4, typename T5>
450     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5)
451     {
452         try
453         {
454             BeginMessage(pszCommand);
455             vSend << a1 << a2 << a3 << a4 << a5;
456             EndMessage();
457         }
458         catch (...)
459         {
460             AbortMessage();
461             throw;
462         }
463     }
464
465     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
466     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6)
467     {
468         try
469         {
470             BeginMessage(pszCommand);
471             vSend << a1 << a2 << a3 << a4 << a5 << a6;
472             EndMessage();
473         }
474         catch (...)
475         {
476             AbortMessage();
477             throw;
478         }
479     }
480
481     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
482     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)
483     {
484         try
485         {
486             BeginMessage(pszCommand);
487             vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7;
488             EndMessage();
489         }
490         catch (...)
491         {
492             AbortMessage();
493             throw;
494         }
495     }
496
497     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
498     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)
499     {
500         try
501         {
502             BeginMessage(pszCommand);
503             vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8;
504             EndMessage();
505         }
506         catch (...)
507         {
508             AbortMessage();
509             throw;
510         }
511     }
512
513     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
514     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)
515     {
516         try
517         {
518             BeginMessage(pszCommand);
519             vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9;
520             EndMessage();
521         }
522         catch (...)
523         {
524             AbortMessage();
525             throw;
526         }
527     }
528
529
530     void PushRequest(const char* pszCommand,
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);
540     }
541
542     template<typename T1>
543     void PushRequest(const char* pszCommand, const T1& a1,
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);
553     }
554
555     template<typename T1, typename T2>
556     void PushRequest(const char* pszCommand, const T1& a1, const T2& a2,
557                      void (*fn)(void*, CDataStream&), void* param1)
558     {
559         uint256 hashReply;
560         RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
561
562         CRITICAL_BLOCK(cs_mapRequests)
563             mapRequests[hashReply] = CRequestTracker(fn, param1);
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     CRITICAL_BLOCK(cs_vNodes)
610         BOOST_FOREACH(CNode* pnode, vNodes)
611             pnode->PushInventory(inv);
612 }
613
614 template<typename T>
615 void RelayMessage(const CInv& inv, const T& a)
616 {
617     CDataStream ss(SER_NETWORK);
618     ss.reserve(10000);
619     ss << a;
620     RelayMessage(inv, ss);
621 }
622
623 template<>
624 inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
625 {
626     CRITICAL_BLOCK(cs_mapRelay)
627     {
628         // Expire old relay messages
629         while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
630         {
631             mapRelay.erase(vRelayExpiration.front().second);
632             vRelayExpiration.pop_front();
633         }
634
635         // Save original serialized message so newer versions are preserved
636         mapRelay[inv] = ss;
637         vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
638     }
639
640     RelayInventory(inv);
641 }
642
643
644
645
646
647
648
649
650 //
651 // Templates for the publish and subscription system.
652 // The object being published as T& obj needs to have:
653 //   a set<unsigned int> setSources member
654 //   specializations of AdvertInsert and AdvertErase
655 // Currently implemented for CTable and CProduct.
656 //
657
658 template<typename T>
659 void AdvertStartPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
660 {
661     // Add to sources
662     obj.setSources.insert(pfrom->addr.ip);
663
664     if (!AdvertInsert(obj))
665         return;
666
667     // Relay
668     CRITICAL_BLOCK(cs_vNodes)
669         BOOST_FOREACH(CNode* pnode, vNodes)
670             if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
671                 pnode->PushMessage("publish", nChannel, nHops, obj);
672 }
673
674 template<typename T>
675 void AdvertStopPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
676 {
677     uint256 hash = obj.GetHash();
678
679     CRITICAL_BLOCK(cs_vNodes)
680         BOOST_FOREACH(CNode* pnode, vNodes)
681             if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
682                 pnode->PushMessage("pub-cancel", nChannel, nHops, hash);
683
684     AdvertErase(obj);
685 }
686
687 template<typename T>
688 void AdvertRemoveSource(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
689 {
690     // Remove a source
691     obj.setSources.erase(pfrom->addr.ip);
692
693     // If no longer supported by any sources, cancel it
694     if (obj.setSources.empty())
695         AdvertStopPublish(pfrom, nChannel, nHops, obj);
696 }
697
698 #endif