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