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