Make some global variables less-global (static)
[novacoin.git] / src / net.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2011 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 __WXMSW__
14 #include <arpa/inet.h>
15 #endif
16
17 class CMessageHeader;
18 class CAddress;
19 class CAddrDB;
20 class CInv;
21 class CRequestTracker;
22 class CNode;
23 class CBlockIndex;
24 extern int nBestHeight;
25 extern int nConnectTimeout;
26
27
28
29 inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer", 10*1000); }
30 inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); }
31 inline unsigned short GetDefaultPort() { return fTestNet ? 18333 : 8333; }
32 static const unsigned int PUBLISH_HOPS = 5;
33 enum
34 {
35     NODE_NETWORK = (1 << 0),
36 };
37
38
39
40
41 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout=nConnectTimeout);
42 bool Lookup(const char *pszName, std::vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
43 bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
44 bool GetMyExternalIP(unsigned int& ipRet);
45 bool AddAddress(CAddress addr, int64 nTimePenalty=0, CAddrDB *pAddrDB=NULL);
46 void AddressCurrentlyConnected(const CAddress& addr);
47 CNode* FindNode(unsigned int ip);
48 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
49 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
50 bool AnySubscribed(unsigned int nChannel);
51 void MapPort(bool fMapPort);
52 void DNSAddressSeed();
53 bool BindListenPort(std::string& strError=REF(std::string()));
54 void StartNode(void* parg);
55 bool StopNode();
56
57
58
59
60
61
62
63
64 //
65 // Message header
66 //  (4) message start
67 //  (12) command
68 //  (4) size
69 //  (4) checksum
70
71 extern unsigned char pchMessageStart[4];
72
73 class CMessageHeader
74 {
75 public:
76     enum { COMMAND_SIZE=12 };
77     char pchMessageStart[sizeof(::pchMessageStart)];
78     char pchCommand[COMMAND_SIZE];
79     unsigned int nMessageSize;
80     unsigned int nChecksum;
81
82     CMessageHeader()
83     {
84         memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
85         memset(pchCommand, 0, sizeof(pchCommand));
86         pchCommand[1] = 1;
87         nMessageSize = -1;
88         nChecksum = 0;
89     }
90
91     CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
92     {
93         memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
94         strncpy(pchCommand, pszCommand, COMMAND_SIZE);
95         nMessageSize = nMessageSizeIn;
96         nChecksum = 0;
97     }
98
99     IMPLEMENT_SERIALIZE
100     (
101         READWRITE(FLATDATA(pchMessageStart));
102         READWRITE(FLATDATA(pchCommand));
103         READWRITE(nMessageSize);
104         if (nVersion >= 209)
105             READWRITE(nChecksum);
106     )
107
108     std::string GetCommand()
109     {
110         if (pchCommand[COMMAND_SIZE-1] == 0)
111             return std::string(pchCommand, pchCommand + strlen(pchCommand));
112         else
113             return std::string(pchCommand, pchCommand + COMMAND_SIZE);
114     }
115
116     bool IsValid()
117     {
118         // Check start string
119         if (memcmp(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)) != 0)
120             return false;
121
122         // Check the command string for errors
123         for (char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
124         {
125             if (*p1 == 0)
126             {
127                 // Must be all zeros after the first zero
128                 for (; p1 < pchCommand + COMMAND_SIZE; p1++)
129                     if (*p1 != 0)
130                         return false;
131             }
132             else if (*p1 < ' ' || *p1 > 0x7E)
133                 return false;
134         }
135
136         // Message size
137         if (nMessageSize > MAX_SIZE)
138         {
139             printf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand().c_str(), nMessageSize);
140             return false;
141         }
142
143         return true;
144     }
145 };
146
147
148
149
150
151
152 static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
153
154 class CAddress
155 {
156 public:
157     uint64 nServices;
158     unsigned char pchReserved[12];
159     unsigned int ip;
160     unsigned short port;
161
162     // disk and network only
163     unsigned int nTime;
164
165     // memory only
166     unsigned int nLastTry;
167
168     CAddress()
169     {
170         Init();
171     }
172
173     CAddress(unsigned int ipIn, unsigned short portIn=0, uint64 nServicesIn=NODE_NETWORK)
174     {
175         Init();
176         ip = ipIn;
177         port = htons(portIn == 0 ? GetDefaultPort() : portIn);
178         nServices = nServicesIn;
179     }
180
181     explicit CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn=NODE_NETWORK)
182     {
183         Init();
184         ip = sockaddr.sin_addr.s_addr;
185         port = sockaddr.sin_port;
186         nServices = nServicesIn;
187     }
188
189     explicit CAddress(const char* pszIn, int portIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK)
190     {
191         Init();
192         Lookup(pszIn, *this, nServicesIn, fNameLookup, portIn);
193     }
194
195     explicit CAddress(const char* pszIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK)
196     {
197         Init();
198         Lookup(pszIn, *this, nServicesIn, fNameLookup, 0, true);
199     }
200
201     explicit CAddress(std::string strIn, int portIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK)
202     {
203         Init();
204         Lookup(strIn.c_str(), *this, nServicesIn, fNameLookup, portIn);
205     }
206
207     explicit CAddress(std::string strIn, bool fNameLookup = false, uint64 nServicesIn=NODE_NETWORK)
208     {
209         Init();
210         Lookup(strIn.c_str(), *this, nServicesIn, fNameLookup, 0, true);
211     }
212
213     void Init()
214     {
215         nServices = NODE_NETWORK;
216         memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
217         ip = INADDR_NONE;
218         port = htons(GetDefaultPort());
219         nTime = 100000000;
220         nLastTry = 0;
221     }
222
223     IMPLEMENT_SERIALIZE
224     (
225         if (fRead)
226             const_cast<CAddress*>(this)->Init();
227         if (nType & SER_DISK)
228             READWRITE(nVersion);
229         if ((nType & SER_DISK) || (nVersion >= 31402 && !(nType & SER_GETHASH)))
230             READWRITE(nTime);
231         READWRITE(nServices);
232         READWRITE(FLATDATA(pchReserved)); // for IPv6
233         READWRITE(ip);
234         READWRITE(port);
235     )
236
237     friend inline bool operator==(const CAddress& a, const CAddress& b)
238     {
239         return (memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved)) == 0 &&
240                 a.ip   == b.ip &&
241                 a.port == b.port);
242     }
243
244     friend inline bool operator!=(const CAddress& a, const CAddress& b)
245     {
246         return (!(a == b));
247     }
248
249     friend inline bool operator<(const CAddress& a, const CAddress& b)
250     {
251         int ret = memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved));
252         if (ret < 0)
253             return true;
254         else if (ret == 0)
255         {
256             if (ntohl(a.ip) < ntohl(b.ip))
257                 return true;
258             else if (a.ip == b.ip)
259                 return ntohs(a.port) < ntohs(b.port);
260         }
261         return false;
262     }
263
264     std::vector<unsigned char> GetKey() const
265     {
266         CDataStream ss;
267         ss.reserve(18);
268         ss << FLATDATA(pchReserved) << ip << port;
269
270         #if defined(_MSC_VER) && _MSC_VER < 1300
271         return std::vector<unsigned char>((unsigned char*)&ss.begin()[0], (unsigned char*)&ss.end()[0]);
272         #else
273         return std::vector<unsigned char>(ss.begin(), ss.end());
274         #endif
275     }
276
277     struct sockaddr_in GetSockAddr() const
278     {
279         struct sockaddr_in sockaddr;
280         memset(&sockaddr, 0, sizeof(sockaddr));
281         sockaddr.sin_family = AF_INET;
282         sockaddr.sin_addr.s_addr = ip;
283         sockaddr.sin_port = port;
284         return sockaddr;
285     }
286
287     bool IsIPv4() const
288     {
289         return (memcmp(pchReserved, pchIPv4, sizeof(pchIPv4)) == 0);
290     }
291
292     bool IsRFC1918() const
293     {
294       return IsIPv4() && (GetByte(3) == 10 ||
295         (GetByte(3) == 192 && GetByte(2) == 168) ||
296         (GetByte(3) == 172 &&
297           (GetByte(2) >= 16 && GetByte(2) <= 31)));
298     }
299
300     bool IsRFC3927() const
301     {
302       return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
303     }
304
305     bool IsLocal() const
306     {
307       return IsIPv4() && (GetByte(3) == 127 ||
308           GetByte(3) == 0);
309     }
310
311     bool IsRoutable() const
312     {
313         return IsValid() &&
314             !(IsRFC1918() || IsRFC3927() || IsLocal());
315     }
316
317     bool IsValid() const
318     {
319         // Clean up 3-byte shifted addresses caused by garbage in size field
320         // of addr messages from versions before 0.2.9 checksum.
321         // Two consecutive addr messages look like this:
322         // header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
323         // so if the first length field is garbled, it reads the second batch
324         // of addr misaligned by 3 bytes.
325         if (memcmp(pchReserved, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
326             return false;
327
328         return (ip != 0 && ip != INADDR_NONE && port != htons(USHRT_MAX));
329     }
330
331     unsigned char GetByte(int n) const
332     {
333         return ((unsigned char*)&ip)[3-n];
334     }
335
336     std::string ToStringIPPort() const
337     {
338         return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
339     }
340
341     std::string ToStringIP() const
342     {
343         return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
344     }
345
346     std::string ToStringPort() const
347     {
348         return strprintf("%u", ntohs(port));
349     }
350
351     std::string ToString() const
352     {
353         return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
354     }
355
356     void print() const
357     {
358         printf("CAddress(%s)\n", ToString().c_str());
359     }
360 };
361
362
363
364
365
366
367
368 enum
369 {
370     MSG_TX = 1,
371     MSG_BLOCK,
372 };
373
374 static const char* ppszTypeName[] =
375 {
376     "ERROR",
377     "tx",
378     "block",
379 };
380
381 class CInv
382 {
383 public:
384     int type;
385     uint256 hash;
386
387     CInv()
388     {
389         type = 0;
390         hash = 0;
391     }
392
393     CInv(int typeIn, const uint256& hashIn)
394     {
395         type = typeIn;
396         hash = hashIn;
397     }
398
399     CInv(const std::string& strType, const uint256& hashIn)
400     {
401         int i;
402         for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
403         {
404             if (strType == ppszTypeName[i])
405             {
406                 type = i;
407                 break;
408             }
409         }
410         if (i == ARRAYLEN(ppszTypeName))
411             throw std::out_of_range(strprintf("CInv::CInv(string, uint256) : unknown type '%s'", strType.c_str()));
412         hash = hashIn;
413     }
414
415     IMPLEMENT_SERIALIZE
416     (
417         READWRITE(type);
418         READWRITE(hash);
419     )
420
421     friend inline bool operator<(const CInv& a, const CInv& b)
422     {
423         return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
424     }
425
426     bool IsKnownType() const
427     {
428         return (type >= 1 && type < ARRAYLEN(ppszTypeName));
429     }
430
431     const char* GetCommand() const
432     {
433         if (!IsKnownType())
434             throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type));
435         return ppszTypeName[type];
436     }
437
438     std::string ToString() const
439     {
440         return strprintf("%s %s", GetCommand(), hash.ToString().substr(0,20).c_str());
441     }
442
443     void print() const
444     {
445         printf("CInv(%s)\n", ToString().c_str());
446     }
447 };
448
449
450
451
452
453 class CRequestTracker
454 {
455 public:
456     void (*fn)(void*, CDataStream&);
457     void* param1;
458
459     explicit CRequestTracker(void (*fnIn)(void*, CDataStream&)=NULL, void* param1In=NULL)
460     {
461         fn = fnIn;
462         param1 = param1In;
463     }
464
465     bool IsNull()
466     {
467         return fn == NULL;
468     }
469 };
470
471
472
473
474
475 extern bool fClient;
476 extern bool fAllowDNS;
477 extern uint64 nLocalServices;
478 extern CAddress addrLocalHost;
479 extern uint64 nLocalHostNonce;
480 extern boost::array<int, 10> vnThreadsRunning;
481
482 extern std::vector<CNode*> vNodes;
483 extern CCriticalSection cs_vNodes;
484 extern std::map<std::vector<unsigned char>, CAddress> mapAddresses;
485 extern CCriticalSection cs_mapAddresses;
486 extern std::map<CInv, CDataStream> mapRelay;
487 extern std::deque<std::pair<int64, CInv> > vRelayExpiration;
488 extern CCriticalSection cs_mapRelay;
489 extern std::map<CInv, int64> mapAlreadyAskedFor;
490
491 // Settings
492 extern int fUseProxy;
493 extern CAddress addrProxy;
494
495
496
497
498
499
500 class CNode
501 {
502 public:
503     // socket
504     uint64 nServices;
505     SOCKET hSocket;
506     CDataStream vSend;
507     CDataStream vRecv;
508     CCriticalSection cs_vSend;
509     CCriticalSection cs_vRecv;
510     int64 nLastSend;
511     int64 nLastRecv;
512     int64 nLastSendEmpty;
513     int64 nTimeConnected;
514     unsigned int nHeaderStart;
515     unsigned int nMessageStart;
516     CAddress addr;
517     int nVersion;
518     std::string strSubVer;
519     bool fClient;
520     bool fInbound;
521     bool fNetworkNode;
522     bool fSuccessfullyConnected;
523     bool fDisconnect;
524 protected:
525     int nRefCount;
526 public:
527     int64 nReleaseTime;
528     std::map<uint256, CRequestTracker> mapRequests;
529     CCriticalSection cs_mapRequests;
530     uint256 hashContinue;
531     CBlockIndex* pindexLastGetBlocksBegin;
532     uint256 hashLastGetBlocksEnd;
533     int nStartingHeight;
534
535     // flood relay
536     std::vector<CAddress> vAddrToSend;
537     std::set<CAddress> setAddrKnown;
538     bool fGetAddr;
539     std::set<uint256> setKnown;
540
541     // inventory based relay
542     std::set<CInv> setInventoryKnown;
543     std::vector<CInv> vInventoryToSend;
544     CCriticalSection cs_inventory;
545     std::multimap<int64, CInv> mapAskFor;
546
547     // publish and subscription
548     std::vector<char> vfSubscribe;
549
550
551     CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false)
552     {
553         nServices = 0;
554         hSocket = hSocketIn;
555         vSend.SetType(SER_NETWORK);
556         vSend.SetVersion(0);
557         vRecv.SetType(SER_NETWORK);
558         vRecv.SetVersion(0);
559         // Version 0.2 obsoletes 20 Feb 2012
560         if (GetTime() > 1329696000)
561         {
562             vSend.SetVersion(209);
563             vRecv.SetVersion(209);
564         }
565         nLastSend = 0;
566         nLastRecv = 0;
567         nLastSendEmpty = GetTime();
568         nTimeConnected = GetTime();
569         nHeaderStart = -1;
570         nMessageStart = -1;
571         addr = addrIn;
572         nVersion = 0;
573         strSubVer = "";
574         fClient = false; // set by version message
575         fInbound = fInboundIn;
576         fNetworkNode = false;
577         fSuccessfullyConnected = false;
578         fDisconnect = false;
579         nRefCount = 0;
580         nReleaseTime = 0;
581         hashContinue = 0;
582         pindexLastGetBlocksBegin = 0;
583         hashLastGetBlocksEnd = 0;
584         nStartingHeight = -1;
585         fGetAddr = false;
586         vfSubscribe.assign(256, false);
587
588         // Be shy and don't send version until we hear
589         if (!fInbound)
590             PushVersion();
591     }
592
593     ~CNode()
594     {
595         if (hSocket != INVALID_SOCKET)
596         {
597             closesocket(hSocket);
598             hSocket = INVALID_SOCKET;
599         }
600     }
601
602 private:
603     CNode(const CNode&);
604     void operator=(const CNode&);
605 public:
606
607
608     int GetRefCount()
609     {
610         return std::max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0);
611     }
612
613     CNode* AddRef(int64 nTimeout=0)
614     {
615         if (nTimeout != 0)
616             nReleaseTime = std::max(nReleaseTime, GetTime() + nTimeout);
617         else
618             nRefCount++;
619         return this;
620     }
621
622     void Release()
623     {
624         nRefCount--;
625     }
626
627
628
629     void AddAddressKnown(const CAddress& addr)
630     {
631         setAddrKnown.insert(addr);
632     }
633
634     void PushAddress(const CAddress& addr)
635     {
636         // Known checking here is only to save space from duplicates.
637         // SendMessages will filter it again for knowns that were added
638         // after addresses were pushed.
639         if (addr.IsValid() && !setAddrKnown.count(addr))
640             vAddrToSend.push_back(addr);
641     }
642
643
644     void AddInventoryKnown(const CInv& inv)
645     {
646         CRITICAL_BLOCK(cs_inventory)
647             setInventoryKnown.insert(inv);
648     }
649
650     void PushInventory(const CInv& inv)
651     {
652         CRITICAL_BLOCK(cs_inventory)
653             if (!setInventoryKnown.count(inv))
654                 vInventoryToSend.push_back(inv);
655     }
656
657     void AskFor(const CInv& inv)
658     {
659         // We're using mapAskFor as a priority queue,
660         // the key is the earliest time the request can be sent
661         int64& nRequestTime = mapAlreadyAskedFor[inv];
662         printf("askfor %s   %"PRI64d"\n", inv.ToString().c_str(), nRequestTime);
663
664         // Make sure not to reuse time indexes to keep things in the same order
665         int64 nNow = (GetTime() - 1) * 1000000;
666         static int64 nLastTime;
667         nLastTime = nNow = std::max(nNow, ++nLastTime);
668
669         // Each retry is 2 minutes after the last
670         nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
671         mapAskFor.insert(std::make_pair(nRequestTime, inv));
672     }
673
674
675
676     void BeginMessage(const char* pszCommand)
677     {
678         cs_vSend.Enter("cs_vSend", __FILE__, __LINE__);
679         if (nHeaderStart != -1)
680             AbortMessage();
681         nHeaderStart = vSend.size();
682         vSend << CMessageHeader(pszCommand, 0);
683         nMessageStart = vSend.size();
684         if (fDebug)
685             printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
686         printf("sending: %s ", pszCommand);
687     }
688
689     void AbortMessage()
690     {
691         if (nHeaderStart == -1)
692             return;
693         vSend.resize(nHeaderStart);
694         nHeaderStart = -1;
695         nMessageStart = -1;
696         cs_vSend.Leave();
697         printf("(aborted)\n");
698     }
699
700     void EndMessage()
701     {
702         if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
703         {
704             printf("dropmessages DROPPING SEND MESSAGE\n");
705             AbortMessage();
706             return;
707         }
708
709         if (nHeaderStart == -1)
710             return;
711
712         // Set the size
713         unsigned int nSize = vSend.size() - nMessageStart;
714         memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
715
716         // Set the checksum
717         if (vSend.GetVersion() >= 209)
718         {
719             uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
720             unsigned int nChecksum = 0;
721             memcpy(&nChecksum, &hash, sizeof(nChecksum));
722             assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum));
723             memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum));
724         }
725
726         printf("(%d bytes) ", nSize);
727         printf("\n");
728
729         nHeaderStart = -1;
730         nMessageStart = -1;
731         cs_vSend.Leave();
732     }
733
734     void EndMessageAbortIfEmpty()
735     {
736         if (nHeaderStart == -1)
737             return;
738         int nSize = vSend.size() - nMessageStart;
739         if (nSize > 0)
740             EndMessage();
741         else
742             AbortMessage();
743     }
744
745
746
747     void PushVersion()
748     {
749         /// when NTP implemented, change to just nTime = GetAdjustedTime()
750         int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
751         CAddress addrYou = (fUseProxy ? CAddress("0.0.0.0") : addr);
752         CAddress addrMe = (fUseProxy ? CAddress("0.0.0.0") : addrLocalHost);
753         RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
754         PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe,
755                     nLocalHostNonce, std::string(pszSubVer), nBestHeight);
756     }
757
758
759
760
761     void PushMessage(const char* pszCommand)
762     {
763         try
764         {
765             BeginMessage(pszCommand);
766             EndMessage();
767         }
768         catch (...)
769         {
770             AbortMessage();
771             throw;
772         }
773     }
774
775     template<typename T1>
776     void PushMessage(const char* pszCommand, const T1& a1)
777     {
778         try
779         {
780             BeginMessage(pszCommand);
781             vSend << a1;
782             EndMessage();
783         }
784         catch (...)
785         {
786             AbortMessage();
787             throw;
788         }
789     }
790
791     template<typename T1, typename T2>
792     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2)
793     {
794         try
795         {
796             BeginMessage(pszCommand);
797             vSend << a1 << a2;
798             EndMessage();
799         }
800         catch (...)
801         {
802             AbortMessage();
803             throw;
804         }
805     }
806
807     template<typename T1, typename T2, typename T3>
808     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3)
809     {
810         try
811         {
812             BeginMessage(pszCommand);
813             vSend << a1 << a2 << a3;
814             EndMessage();
815         }
816         catch (...)
817         {
818             AbortMessage();
819             throw;
820         }
821     }
822
823     template<typename T1, typename T2, typename T3, typename T4>
824     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4)
825     {
826         try
827         {
828             BeginMessage(pszCommand);
829             vSend << a1 << a2 << a3 << a4;
830             EndMessage();
831         }
832         catch (...)
833         {
834             AbortMessage();
835             throw;
836         }
837     }
838
839     template<typename T1, typename T2, typename T3, typename T4, typename T5>
840     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5)
841     {
842         try
843         {
844             BeginMessage(pszCommand);
845             vSend << a1 << a2 << a3 << a4 << a5;
846             EndMessage();
847         }
848         catch (...)
849         {
850             AbortMessage();
851             throw;
852         }
853     }
854
855     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
856     void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6)
857     {
858         try
859         {
860             BeginMessage(pszCommand);
861             vSend << a1 << a2 << a3 << a4 << a5 << a6;
862             EndMessage();
863         }
864         catch (...)
865         {
866             AbortMessage();
867             throw;
868         }
869     }
870
871     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
872     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)
873     {
874         try
875         {
876             BeginMessage(pszCommand);
877             vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7;
878             EndMessage();
879         }
880         catch (...)
881         {
882             AbortMessage();
883             throw;
884         }
885     }
886
887     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
888     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)
889     {
890         try
891         {
892             BeginMessage(pszCommand);
893             vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8;
894             EndMessage();
895         }
896         catch (...)
897         {
898             AbortMessage();
899             throw;
900         }
901     }
902
903     template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
904     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)
905     {
906         try
907         {
908             BeginMessage(pszCommand);
909             vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9;
910             EndMessage();
911         }
912         catch (...)
913         {
914             AbortMessage();
915             throw;
916         }
917     }
918
919
920     void PushRequest(const char* pszCommand,
921                      void (*fn)(void*, CDataStream&), void* param1)
922     {
923         uint256 hashReply;
924         RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
925
926         CRITICAL_BLOCK(cs_mapRequests)
927             mapRequests[hashReply] = CRequestTracker(fn, param1);
928
929         PushMessage(pszCommand, hashReply);
930     }
931
932     template<typename T1>
933     void PushRequest(const char* pszCommand, const T1& a1,
934                      void (*fn)(void*, CDataStream&), void* param1)
935     {
936         uint256 hashReply;
937         RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
938
939         CRITICAL_BLOCK(cs_mapRequests)
940             mapRequests[hashReply] = CRequestTracker(fn, param1);
941
942         PushMessage(pszCommand, hashReply, a1);
943     }
944
945     template<typename T1, typename T2>
946     void PushRequest(const char* pszCommand, const T1& a1, const T2& a2,
947                      void (*fn)(void*, CDataStream&), void* param1)
948     {
949         uint256 hashReply;
950         RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
951
952         CRITICAL_BLOCK(cs_mapRequests)
953             mapRequests[hashReply] = CRequestTracker(fn, param1);
954
955         PushMessage(pszCommand, hashReply, a1, a2);
956     }
957
958
959
960     void PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd);
961     bool IsSubscribed(unsigned int nChannel);
962     void Subscribe(unsigned int nChannel, unsigned int nHops=0);
963     void CancelSubscribe(unsigned int nChannel);
964     void CloseSocketDisconnect();
965     void Cleanup();
966 };
967
968
969
970
971
972
973
974
975
976
977 inline void RelayInventory(const CInv& inv)
978 {
979     // Put on lists to offer to the other nodes
980     CRITICAL_BLOCK(cs_vNodes)
981         BOOST_FOREACH(CNode* pnode, vNodes)
982             pnode->PushInventory(inv);
983 }
984
985 template<typename T>
986 void RelayMessage(const CInv& inv, const T& a)
987 {
988     CDataStream ss(SER_NETWORK);
989     ss.reserve(10000);
990     ss << a;
991     RelayMessage(inv, ss);
992 }
993
994 template<>
995 inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
996 {
997     CRITICAL_BLOCK(cs_mapRelay)
998     {
999         // Expire old relay messages
1000         while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1001         {
1002             mapRelay.erase(vRelayExpiration.front().second);
1003             vRelayExpiration.pop_front();
1004         }
1005
1006         // Save original serialized message so newer versions are preserved
1007         mapRelay[inv] = ss;
1008         vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1009     }
1010
1011     RelayInventory(inv);
1012 }
1013
1014
1015
1016
1017
1018
1019
1020
1021 //
1022 // Templates for the publish and subscription system.
1023 // The object being published as T& obj needs to have:
1024 //   a set<unsigned int> setSources member
1025 //   specializations of AdvertInsert and AdvertErase
1026 // Currently implemented for CTable and CProduct.
1027 //
1028
1029 template<typename T>
1030 void AdvertStartPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
1031 {
1032     // Add to sources
1033     obj.setSources.insert(pfrom->addr.ip);
1034
1035     if (!AdvertInsert(obj))
1036         return;
1037
1038     // Relay
1039     CRITICAL_BLOCK(cs_vNodes)
1040         BOOST_FOREACH(CNode* pnode, vNodes)
1041             if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
1042                 pnode->PushMessage("publish", nChannel, nHops, obj);
1043 }
1044
1045 template<typename T>
1046 void AdvertStopPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
1047 {
1048     uint256 hash = obj.GetHash();
1049
1050     CRITICAL_BLOCK(cs_vNodes)
1051         BOOST_FOREACH(CNode* pnode, vNodes)
1052             if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
1053                 pnode->PushMessage("pub-cancel", nChannel, nHops, hash);
1054
1055     AdvertErase(obj);
1056 }
1057
1058 template<typename T>
1059 void AdvertRemoveSource(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
1060 {
1061     // Remove a source
1062     obj.setSources.erase(pfrom->addr.ip);
1063
1064     // If no longer supported by any sources, cancel it
1065     if (obj.setSources.empty())
1066         AdvertStopPublish(pfrom, nChannel, nHops, obj);
1067 }
1068
1069 #endif