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