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.
11 extern int nBestHeight
;
15 static const unsigned short DEFAULT_PORT
= 0x8d20; // htons(8333)
16 static const unsigned int PUBLISH_HOPS
= 5;
19 NODE_NETWORK
= (1 << 0),
25 bool ConnectSocket(const CAddress
& addrConnect
, SOCKET
& hSocketRet
);
26 bool GetMyExternalIP(unsigned int& ipRet
);
27 bool AddAddress(CAddress addr
);
28 void AddressCurrentlyConnected(const CAddress
& addr
);
29 CNode
* FindNode(unsigned int ip
);
30 CNode
* ConnectNode(CAddress addrConnect
, int64 nTimeout
=0);
31 void AbandonRequests(void (*fn
)(void*, CDataStream
&), void* param1
);
32 bool AnySubscribed(unsigned int nChannel
);
33 bool BindListenPort(string
& strError
=REF(string()));
34 void StartNode(void* parg
);
51 extern char pchMessageStart
[4];
56 enum { COMMAND_SIZE
=12 };
57 char pchMessageStart
[sizeof(::pchMessageStart
)];
58 char pchCommand
[COMMAND_SIZE
];
59 unsigned int nMessageSize
;
60 unsigned int nChecksum
;
64 memcpy(pchMessageStart
, ::pchMessageStart
, sizeof(pchMessageStart
));
65 memset(pchCommand
, 0, sizeof(pchCommand
));
71 CMessageHeader(const char* pszCommand
, unsigned int nMessageSizeIn
)
73 memcpy(pchMessageStart
, ::pchMessageStart
, sizeof(pchMessageStart
));
74 strncpy(pchCommand
, pszCommand
, COMMAND_SIZE
);
75 nMessageSize
= nMessageSizeIn
;
81 READWRITE(FLATDATA(pchMessageStart
));
82 READWRITE(FLATDATA(pchCommand
));
83 READWRITE(nMessageSize
);
90 if (pchCommand
[COMMAND_SIZE
-1] == 0)
91 return string(pchCommand
, pchCommand
+ strlen(pchCommand
));
93 return string(pchCommand
, pchCommand
+ COMMAND_SIZE
);
99 if (memcmp(pchMessageStart
, ::pchMessageStart
, sizeof(pchMessageStart
)) != 0)
102 // Check the command string for errors
103 for (char* p1
= pchCommand
; p1
< pchCommand
+ COMMAND_SIZE
; p1
++)
107 // Must be all zeros after the first zero
108 for (; p1
< pchCommand
+ COMMAND_SIZE
; p1
++)
112 else if (*p1
< ' ' || *p1
> 0x7E)
117 if (nMessageSize
> MAX_SIZE
)
119 printf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand().c_str(), nMessageSize
);
132 static const unsigned char pchIPv4
[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
138 unsigned char pchReserved
[12];
146 unsigned int nLastTry
;
153 CAddress(unsigned int ipIn
, unsigned short portIn
=DEFAULT_PORT
, uint64 nServicesIn
=NODE_NETWORK
)
158 nServices
= nServicesIn
;
161 explicit CAddress(const struct sockaddr_in
& sockaddr
, uint64 nServicesIn
=NODE_NETWORK
)
164 ip
= sockaddr
.sin_addr
.s_addr
;
165 port
= sockaddr
.sin_port
;
166 nServices
= nServicesIn
;
169 explicit CAddress(const char* pszIn
, uint64 nServicesIn
=NODE_NETWORK
)
173 nServices
= nServicesIn
;
176 explicit CAddress(string strIn
, uint64 nServicesIn
=NODE_NETWORK
)
179 SetAddress(strIn
.c_str());
180 nServices
= nServicesIn
;
185 nServices
= NODE_NETWORK
;
186 memcpy(pchReserved
, pchIPv4
, sizeof(pchReserved
));
189 nTime
= GetAdjustedTime();
193 bool SetAddress(const char* pszIn
)
198 strlcpy(psz
, pszIn
, sizeof(psz
));
199 unsigned int a
=0, b
=0, c
=0, d
=0, e
=0;
200 if (sscanf(psz
, "%u.%u.%u.%u:%u", &a
, &b
, &c
, &d
, &e
) < 4)
202 char* pszPort
= strchr(psz
, ':');
206 port
= htons(atoi(pszPort
));
207 if (atoi(pszPort
) < 0 || atoi(pszPort
) > USHRT_MAX
)
208 port
= htons(USHRT_MAX
);
214 bool SetAddress(string strIn
)
216 return SetAddress(strIn
.c_str());
221 if (nType
& SER_DISK
)
226 READWRITE(nServices
);
227 READWRITE(FLATDATA(pchReserved
)); // for IPv6
232 friend inline bool operator==(const CAddress
& a
, const CAddress
& b
)
234 return (memcmp(a
.pchReserved
, b
.pchReserved
, sizeof(a
.pchReserved
)) == 0 &&
239 friend inline bool operator!=(const CAddress
& a
, const CAddress
& b
)
244 friend inline bool operator<(const CAddress
& a
, const CAddress
& b
)
246 int ret
= memcmp(a
.pchReserved
, b
.pchReserved
, sizeof(a
.pchReserved
));
251 if (ntohl(a
.ip
) < ntohl(b
.ip
))
253 else if (a
.ip
== b
.ip
)
254 return ntohs(a
.port
) < ntohs(b
.port
);
259 vector
<unsigned char> GetKey() const
263 ss
<< FLATDATA(pchReserved
) << ip
<< port
;
265 #if defined(_MSC_VER) && _MSC_VER < 1300
266 return vector
<unsigned char>((unsigned char*)&ss
.begin()[0], (unsigned char*)&ss
.end()[0]);
268 return vector
<unsigned char>(ss
.begin(), ss
.end());
272 struct sockaddr_in
GetSockAddr() const
274 struct sockaddr_in sockaddr
;
275 memset(&sockaddr
, 0, sizeof(sockaddr
));
276 sockaddr
.sin_family
= AF_INET
;
277 sockaddr
.sin_addr
.s_addr
= ip
;
278 sockaddr
.sin_port
= port
;
284 return (memcmp(pchReserved
, pchIPv4
, sizeof(pchIPv4
)) == 0);
287 bool IsRoutable() const
290 !(GetByte(3) == 10 ||
291 (GetByte(3) == 192 && GetByte(2) == 168) ||
298 // Clean up 3-byte shifted addresses caused by garbage in size field
299 // of addr messages from versions before 0.2.9 checksum.
300 // Two consecutive addr messages look like this:
301 // header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
302 // so if the first length field is garbled, it reads the second batch
303 // of addr misaligned by 3 bytes.
304 if (memcmp(pchReserved
, pchIPv4
+3, sizeof(pchIPv4
)-3) == 0)
307 return (ip
!= 0 && ip
!= INADDR_NONE
&& port
!= htons(USHRT_MAX
));
310 unsigned char GetByte(int n
) const
312 return ((unsigned char*)&ip
)[3-n
];
315 string
ToStringIPPort() const
317 return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port
));
320 string
ToStringIP() const
322 return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
325 string
ToStringPort() const
327 return strprintf("%u", ntohs(port
));
330 string
ToStringLog() const
335 string
ToString() const
337 return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port
));
342 printf("CAddress(%s)\n", ToString().c_str());
358 static const char* ppszTypeName
[] =
377 CInv(int typeIn
, const uint256
& hashIn
)
383 CInv(const string
& strType
, const uint256
& hashIn
)
386 for (i
= 1; i
< ARRAYLEN(ppszTypeName
); i
++)
388 if (strType
== ppszTypeName
[i
])
394 if (i
== ARRAYLEN(ppszTypeName
))
395 throw std::out_of_range(strprintf("CInv::CInv(string, uint256) : unknown type '%s'", strType
.c_str()));
405 friend inline bool operator<(const CInv
& a
, const CInv
& b
)
407 return (a
.type
< b
.type
|| (a
.type
== b
.type
&& a
.hash
< b
.hash
));
410 bool IsKnownType() const
412 return (type
>= 1 && type
< ARRAYLEN(ppszTypeName
));
415 const char* GetCommand() const
418 throw std::out_of_range(strprintf("CInv::GetCommand() : type=% unknown type", type
));
419 return ppszTypeName
[type
];
422 string
ToString() const
424 return strprintf("%s %s", GetCommand(), hash
.ToString().substr(0,20).c_str());
429 printf("CInv(%s)\n", ToString().c_str());
437 class CRequestTracker
440 void (*fn
)(void*, CDataStream
&);
443 explicit CRequestTracker(void (*fnIn
)(void*, CDataStream
&)=NULL
, void* param1In
=NULL
)
460 extern uint64 nLocalServices
;
461 extern CAddress addrLocalHost
;
462 extern CNode
* pnodeLocalHost
;
463 extern uint64 nLocalHostNonce
;
464 extern array
<int, 10> vnThreadsRunning
;
465 extern SOCKET hListenSocket
;
467 extern vector
<CNode
*> vNodes
;
468 extern CCriticalSection cs_vNodes
;
469 extern map
<vector
<unsigned char>, CAddress
> mapAddresses
;
470 extern CCriticalSection cs_mapAddresses
;
471 extern map
<CInv
, CDataStream
> mapRelay
;
472 extern deque
<pair
<int64
, CInv
> > vRelayExpiration
;
473 extern CCriticalSection cs_mapRelay
;
474 extern map
<CInv
, int64
> mapAlreadyAskedFor
;
477 extern int fUseProxy
;
478 extern CAddress addrProxy
;
493 CCriticalSection cs_vSend
;
494 CCriticalSection cs_vRecv
;
497 int64 nLastSendEmpty
;
498 int64 nTimeConnected
;
499 unsigned int nHeaderStart
;
500 unsigned int nMessageStart
;
507 bool fSuccessfullyConnected
;
513 map
<uint256
, CRequestTracker
> mapRequests
;
514 CCriticalSection cs_mapRequests
;
515 uint256 hashContinue
;
516 CBlockIndex
* pindexLastGetBlocksBegin
;
517 uint256 hashLastGetBlocksEnd
;
521 vector
<CAddress
> vAddrToSend
;
522 set
<CAddress
> setAddrKnown
;
524 set
<uint256
> setKnown
;
526 // inventory based relay
527 set
<CInv
> setInventoryKnown
;
528 vector
<CInv
> vInventoryToSend
;
529 CCriticalSection cs_inventory
;
530 multimap
<int64
, CInv
> mapAskFor
;
532 // publish and subscription
533 vector
<char> vfSubscribe
;
536 CNode(SOCKET hSocketIn
, CAddress addrIn
, bool fInboundIn
=false)
540 vSend
.SetType(SER_NETWORK
);
542 vRecv
.SetType(SER_NETWORK
);
544 // Version 0.2 obsoletes 20 Feb 2012
545 if (GetTime() > 1329696000)
547 vSend
.SetVersion(209);
548 vRecv
.SetVersion(209);
552 nLastSendEmpty
= GetTime();
553 nTimeConnected
= GetTime();
559 fClient
= false; // set by version message
560 fInbound
= fInboundIn
;
561 fNetworkNode
= false;
562 fSuccessfullyConnected
= false;
567 pindexLastGetBlocksBegin
= 0;
568 hashLastGetBlocksEnd
= 0;
569 nStartingHeight
= -1;
571 vfSubscribe
.assign(256, false);
573 // Push a version message
574 /// when NTP implemented, change to just nTime = GetAdjustedTime()
575 int64 nTime
= (fInbound
? GetAdjustedTime() : GetTime());
576 CAddress addrYou
= (fUseProxy
? CAddress("0.0.0.0") : addr
);
577 CAddress addrMe
= (fUseProxy
? CAddress("0.0.0.0") : addrLocalHost
);
578 RAND_bytes((unsigned char*)&nLocalHostNonce
, sizeof(nLocalHostNonce
));
579 PushMessage("version", VERSION
, nLocalServices
, nTime
, addrYou
, addrMe
,
580 nLocalHostNonce
, string(pszSubVer
), nBestHeight
);
585 if (hSocket
!= INVALID_SOCKET
)
587 closesocket(hSocket
);
588 hSocket
= INVALID_SOCKET
;
594 void operator=(const CNode
&);
600 return max(nRefCount
, 0) + (GetTime() < nReleaseTime
? 1 : 0);
603 CNode
* AddRef(int64 nTimeout
=0)
606 nReleaseTime
= max(nReleaseTime
, GetTime() + nTimeout
);
619 void AddAddressKnown(const CAddress
& addr
)
621 setAddrKnown
.insert(addr
);
624 void PushAddress(const CAddress
& addr
)
626 // Known checking here is only to save space from duplicates.
627 // SendMessages will filter it again for knowns that were added
628 // after addresses were pushed.
629 if (addr
.IsValid() && !setAddrKnown
.count(addr
))
630 vAddrToSend
.push_back(addr
);
634 void AddInventoryKnown(const CInv
& inv
)
636 CRITICAL_BLOCK(cs_inventory
)
637 setInventoryKnown
.insert(inv
);
640 void PushInventory(const CInv
& inv
)
642 CRITICAL_BLOCK(cs_inventory
)
643 if (!setInventoryKnown
.count(inv
))
644 vInventoryToSend
.push_back(inv
);
647 void AskFor(const CInv
& inv
)
649 // We're using mapAskFor as a priority queue,
650 // the key is the earliest time the request can be sent
651 int64
& nRequestTime
= mapAlreadyAskedFor
[inv
];
652 printf("askfor %s %"PRI64d
"\n", inv
.ToString().c_str(), nRequestTime
);
654 // Make sure not to reuse time indexes to keep things in the same order
655 int64 nNow
= (GetTime() - 1) * 1000000;
656 static int64 nLastTime
;
657 nLastTime
= nNow
= max(nNow
, ++nLastTime
);
659 // Each retry is 2 minutes after the last
660 nRequestTime
= max(nRequestTime
+ 2 * 60 * 1000000, nNow
);
661 mapAskFor
.insert(make_pair(nRequestTime
, inv
));
666 void BeginMessage(const char* pszCommand
)
669 if (nHeaderStart
!= -1)
671 nHeaderStart
= vSend
.size();
672 vSend
<< CMessageHeader(pszCommand
, 0);
673 nMessageStart
= vSend
.size();
675 printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
676 printf("sending: %s ", pszCommand
);
681 if (nHeaderStart
== -1)
683 vSend
.resize(nHeaderStart
);
687 printf("(aborted)\n");
692 if (mapArgs
.count("-dropmessagestest") && GetRand(atoi(mapArgs
["-dropmessagestest"])) == 0)
694 printf("dropmessages DROPPING SEND MESSAGE\n");
699 if (nHeaderStart
== -1)
703 unsigned int nSize
= vSend
.size() - nMessageStart
;
704 memcpy((char*)&vSend
[nHeaderStart
] + offsetof(CMessageHeader
, nMessageSize
), &nSize
, sizeof(nSize
));
707 if (vSend
.GetVersion() >= 209)
709 uint256 hash
= Hash(vSend
.begin() + nMessageStart
, vSend
.end());
710 unsigned int nChecksum
= 0;
711 memcpy(&nChecksum
, &hash
, sizeof(nChecksum
));
712 assert(nMessageStart
- nHeaderStart
>= offsetof(CMessageHeader
, nChecksum
) + sizeof(nChecksum
));
713 memcpy((char*)&vSend
[nHeaderStart
] + offsetof(CMessageHeader
, nChecksum
), &nChecksum
, sizeof(nChecksum
));
716 printf("(%d bytes) ", nSize
);
724 void EndMessageAbortIfEmpty()
726 if (nHeaderStart
== -1)
728 int nSize
= vSend
.size() - nMessageStart
;
735 const char* GetMessageCommand() const
737 if (nHeaderStart
== -1)
739 return &vSend
[nHeaderStart
] + offsetof(CMessageHeader
, pchCommand
);
745 void PushMessage(const char* pszCommand
)
749 BeginMessage(pszCommand
);
759 template<typename T1
>
760 void PushMessage(const char* pszCommand
, const T1
& a1
)
764 BeginMessage(pszCommand
);
775 template<typename T1
, typename T2
>
776 void PushMessage(const char* pszCommand
, const T1
& a1
, const T2
& a2
)
780 BeginMessage(pszCommand
);
791 template<typename T1
, typename T2
, typename T3
>
792 void PushMessage(const char* pszCommand
, const T1
& a1
, const T2
& a2
, const T3
& a3
)
796 BeginMessage(pszCommand
);
797 vSend
<< a1
<< a2
<< a3
;
807 template<typename T1
, typename T2
, typename T3
, typename T4
>
808 void PushMessage(const char* pszCommand
, const T1
& a1
, const T2
& a2
, const T3
& a3
, const T4
& a4
)
812 BeginMessage(pszCommand
);
813 vSend
<< a1
<< a2
<< a3
<< a4
;
823 template<typename T1
, typename T2
, typename T3
, typename T4
, typename T5
>
824 void PushMessage(const char* pszCommand
, const T1
& a1
, const T2
& a2
, const T3
& a3
, const T4
& a4
, const T5
& a5
)
828 BeginMessage(pszCommand
);
829 vSend
<< a1
<< a2
<< a3
<< a4
<< a5
;
839 template<typename T1
, typename T2
, typename T3
, typename T4
, typename T5
, typename T6
>
840 void PushMessage(const char* pszCommand
, const T1
& a1
, const T2
& a2
, const T3
& a3
, const T4
& a4
, const T5
& a5
, const T6
& a6
)
844 BeginMessage(pszCommand
);
845 vSend
<< a1
<< a2
<< a3
<< a4
<< a5
<< a6
;
855 template<typename T1
, typename T2
, typename T3
, typename T4
, typename T5
, typename T6
, typename T7
>
856 void PushMessage(const char* pszCommand
, const T1
& a1
, const T2
& a2
, const T3
& a3
, const T4
& a4
, const T5
& a5
, const T6
& a6
, const T7
& a7
)
860 BeginMessage(pszCommand
);
861 vSend
<< a1
<< a2
<< a3
<< a4
<< a5
<< a6
<< a7
;
871 template<typename T1
, typename T2
, typename T3
, typename T4
, typename T5
, typename T6
, typename T7
, typename T8
>
872 void PushMessage(const char* pszCommand
, const T1
& a1
, const T2
& a2
, const T3
& a3
, const T4
& a4
, const T5
& a5
, const T6
& a6
, const T7
& a7
, const T8
& a8
)
876 BeginMessage(pszCommand
);
877 vSend
<< a1
<< a2
<< a3
<< a4
<< a5
<< a6
<< a7
<< a8
;
887 template<typename T1
, typename T2
, typename T3
, typename T4
, typename T5
, typename T6
, typename T7
, typename T8
, typename T9
>
888 void PushMessage(const char* pszCommand
, const T1
& a1
, const T2
& a2
, const T3
& a3
, const T4
& a4
, const T5
& a5
, const T6
& a6
, const T7
& a7
, const T8
& a8
, const T9
& a9
)
892 BeginMessage(pszCommand
);
893 vSend
<< a1
<< a2
<< a3
<< a4
<< a5
<< a6
<< a7
<< a8
<< a9
;
904 void PushRequest(const char* pszCommand
,
905 void (*fn
)(void*, CDataStream
&), void* param1
)
908 RAND_bytes((unsigned char*)&hashReply
, sizeof(hashReply
));
910 CRITICAL_BLOCK(cs_mapRequests
)
911 mapRequests
[hashReply
] = CRequestTracker(fn
, param1
);
913 PushMessage(pszCommand
, hashReply
);
916 template<typename T1
>
917 void PushRequest(const char* pszCommand
, const T1
& a1
,
918 void (*fn
)(void*, CDataStream
&), void* param1
)
921 RAND_bytes((unsigned char*)&hashReply
, sizeof(hashReply
));
923 CRITICAL_BLOCK(cs_mapRequests
)
924 mapRequests
[hashReply
] = CRequestTracker(fn
, param1
);
926 PushMessage(pszCommand
, hashReply
, a1
);
929 template<typename T1
, typename T2
>
930 void PushRequest(const char* pszCommand
, const T1
& a1
, const T2
& a2
,
931 void (*fn
)(void*, CDataStream
&), void* param1
)
934 RAND_bytes((unsigned char*)&hashReply
, sizeof(hashReply
));
936 CRITICAL_BLOCK(cs_mapRequests
)
937 mapRequests
[hashReply
] = CRequestTracker(fn
, param1
);
939 PushMessage(pszCommand
, hashReply
, a1
, a2
);
944 void PushGetBlocks(CBlockIndex
* pindexBegin
, uint256 hashEnd
);
945 bool IsSubscribed(unsigned int nChannel
);
946 void Subscribe(unsigned int nChannel
, unsigned int nHops
=0);
947 void CancelSubscribe(unsigned int nChannel
);
948 void CloseSocketDisconnect();
961 inline void RelayInventory(const CInv
& inv
)
963 // Put on lists to offer to the other nodes
964 CRITICAL_BLOCK(cs_vNodes
)
965 foreach(CNode
* pnode
, vNodes
)
966 pnode
->PushInventory(inv
);
970 void RelayMessage(const CInv
& inv
, const T
& a
)
972 CDataStream
ss(SER_NETWORK
);
975 RelayMessage(inv
, ss
);
979 inline void RelayMessage
<>(const CInv
& inv
, const CDataStream
& ss
)
981 CRITICAL_BLOCK(cs_mapRelay
)
983 // Expire old relay messages
984 while (!vRelayExpiration
.empty() && vRelayExpiration
.front().first
< GetTime())
986 mapRelay
.erase(vRelayExpiration
.front().second
);
987 vRelayExpiration
.pop_front();
990 // Save original serialized message so newer versions are preserved
992 vRelayExpiration
.push_back(make_pair(GetTime() + 15 * 60, inv
));
1006 // Templates for the publish and subscription system.
1007 // The object being published as T& obj needs to have:
1008 // a set<unsigned int> setSources member
1009 // specializations of AdvertInsert and AdvertErase
1010 // Currently implemented for CTable and CProduct.
1013 template<typename T
>
1014 void AdvertStartPublish(CNode
* pfrom
, unsigned int nChannel
, unsigned int nHops
, T
& obj
)
1017 obj
.setSources
.insert(pfrom
->addr
.ip
);
1019 if (!AdvertInsert(obj
))
1023 CRITICAL_BLOCK(cs_vNodes
)
1024 foreach(CNode
* pnode
, vNodes
)
1025 if (pnode
!= pfrom
&& (nHops
< PUBLISH_HOPS
|| pnode
->IsSubscribed(nChannel
)))
1026 pnode
->PushMessage("publish", nChannel
, nHops
, obj
);
1029 template<typename T
>
1030 void AdvertStopPublish(CNode
* pfrom
, unsigned int nChannel
, unsigned int nHops
, T
& obj
)
1032 uint256 hash
= obj
.GetHash();
1034 CRITICAL_BLOCK(cs_vNodes
)
1035 foreach(CNode
* pnode
, vNodes
)
1036 if (pnode
!= pfrom
&& (nHops
< PUBLISH_HOPS
|| pnode
->IsSubscribed(nChannel
)))
1037 pnode
->PushMessage("pub-cancel", nChannel
, nHops
, hash
);
1042 template<typename T
>
1043 void AdvertRemoveSource(CNode
* pfrom
, unsigned int nChannel
, unsigned int nHops
, T
& obj
)
1046 obj
.setSources
.erase(pfrom
->addr
.ip
);
1048 // If no longer supported by any sources, cancel it
1049 if (obj
.setSources
.empty())
1050 AdvertStopPublish(pfrom
, nChannel
, nHops
, obj
);