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