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