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