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