1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2018 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include <protocol.h>
7
8 #include <util/system.h>
9 #include <util/strencodings.h>
10
11 #ifndef WIN32
12 # include <arpa/inet.h>
13 #endif
14
15 static std::atomic<bool> g_initial_block_download_completed(false);
16
17 namespace NetMsgType {
18 const char *VERSION="version";
19 const char *VERACK="verack";
20 const char *ADDR="addr";
21 const char *INV="inv";
22 const char *GETDATA="getdata";
23 const char *MERKLEBLOCK="merkleblock";
24 const char *GETBLOCKS="getblocks";
25 const char *GETHEADERS="getheaders";
26 const char *TX="tx";
27 const char *HEADERS="headers";
28 const char *BLOCK="block";
29 const char *GETADDR="getaddr";
30 const char *MEMPOOL="mempool";
31 const char *PING="ping";
32 const char *PONG="pong";
33 const char *NOTFOUND="notfound";
34 const char *FILTERLOAD="filterload";
35 const char *FILTERADD="filteradd";
36 const char *FILTERCLEAR="filterclear";
37 const char *SENDHEADERS="sendheaders";
38 const char *FEEFILTER="feefilter";
39 const char *SENDCMPCT="sendcmpct";
40 const char *CMPCTBLOCK="cmpctblock";
41 const char *GETBLOCKTXN="getblocktxn";
42 const char *BLOCKTXN="blocktxn";
43 } // namespace NetMsgType
44
45 /** All known message types. Keep this in the same order as the list of
46 * messages above and in protocol.h.
47 */
48 const static std::string allNetMessageTypes[] = {
49 NetMsgType::VERSION,
50 NetMsgType::VERACK,
51 NetMsgType::ADDR,
52 NetMsgType::INV,
53 NetMsgType::GETDATA,
54 NetMsgType::MERKLEBLOCK,
55 NetMsgType::GETBLOCKS,
56 NetMsgType::GETHEADERS,
57 NetMsgType::TX,
58 NetMsgType::HEADERS,
59 NetMsgType::BLOCK,
60 NetMsgType::GETADDR,
61 NetMsgType::MEMPOOL,
62 NetMsgType::PING,
63 NetMsgType::PONG,
64 NetMsgType::NOTFOUND,
65 NetMsgType::FILTERLOAD,
66 NetMsgType::FILTERADD,
67 NetMsgType::FILTERCLEAR,
68 NetMsgType::SENDHEADERS,
69 NetMsgType::FEEFILTER,
70 NetMsgType::SENDCMPCT,
71 NetMsgType::CMPCTBLOCK,
72 NetMsgType::GETBLOCKTXN,
73 NetMsgType::BLOCKTXN,
74 };
75 const static std::vector<std::string> allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes));
76
CMessageHeader(const MessageStartChars & pchMessageStartIn)77 CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn)
78 {
79 memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
80 memset(pchCommand, 0, sizeof(pchCommand));
81 nMessageSize = -1;
82 memset(pchChecksum, 0, CHECKSUM_SIZE);
83 }
84
CMessageHeader(const MessageStartChars & pchMessageStartIn,const char * pszCommand,unsigned int nMessageSizeIn)85 CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn)
86 {
87 memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
88
89 // Copy the command name, zero-padding to COMMAND_SIZE bytes
90 size_t i = 0;
91 for (; i < COMMAND_SIZE && pszCommand[i] != 0; ++i) pchCommand[i] = pszCommand[i];
92 assert(pszCommand[i] == 0); // Assert that the command name passed in is not longer than COMMAND_SIZE
93 for (; i < COMMAND_SIZE; ++i) pchCommand[i] = 0;
94
95 nMessageSize = nMessageSizeIn;
96 memset(pchChecksum, 0, CHECKSUM_SIZE);
97 }
98
GetCommand() const99 std::string CMessageHeader::GetCommand() const
100 {
101 return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
102 }
103
IsValid(const MessageStartChars & pchMessageStartIn) const104 bool CMessageHeader::IsValid(const MessageStartChars& pchMessageStartIn) const
105 {
106 // Check start string
107 if (memcmp(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE) != 0)
108 return false;
109
110 // Check the command string for errors
111 for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
112 {
113 if (*p1 == 0)
114 {
115 // Must be all zeros after the first zero
116 for (; p1 < pchCommand + COMMAND_SIZE; p1++)
117 if (*p1 != 0)
118 return false;
119 }
120 else if (*p1 < ' ' || *p1 > 0x7E)
121 return false;
122 }
123
124 // Message size
125 if (nMessageSize > MAX_SIZE)
126 {
127 LogPrintf("CMessageHeader::IsValid(): (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand(), nMessageSize);
128 return false;
129 }
130
131 return true;
132 }
133
134
GetDesirableServiceFlags(ServiceFlags services)135 ServiceFlags GetDesirableServiceFlags(ServiceFlags services) {
136 if ((services & NODE_NETWORK_LIMITED) && g_initial_block_download_completed) {
137 return ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS);
138 }
139 return ServiceFlags(NODE_NETWORK | NODE_WITNESS);
140 }
141
SetServiceFlagsIBDCache(bool state)142 void SetServiceFlagsIBDCache(bool state) {
143 g_initial_block_download_completed = state;
144 }
145
146
CAddress()147 CAddress::CAddress() : CService()
148 {
149 Init();
150 }
151
CAddress(CService ipIn,ServiceFlags nServicesIn)152 CAddress::CAddress(CService ipIn, ServiceFlags nServicesIn) : CService(ipIn)
153 {
154 Init();
155 nServices = nServicesIn;
156 }
157
Init()158 void CAddress::Init()
159 {
160 nServices = NODE_NONE;
161 nTime = 100000000;
162 }
163
CInv()164 CInv::CInv()
165 {
166 type = 0;
167 hash.SetNull();
168 }
169
CInv(int typeIn,const uint256 & hashIn)170 CInv::CInv(int typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {}
171
operator <(const CInv & a,const CInv & b)172 bool operator<(const CInv& a, const CInv& b)
173 {
174 return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
175 }
176
GetCommand() const177 std::string CInv::GetCommand() const
178 {
179 std::string cmd;
180 if (type & MSG_WITNESS_FLAG)
181 cmd.append("witness-");
182 int masked = type & MSG_TYPE_MASK;
183 switch (masked)
184 {
185 case MSG_TX: return cmd.append(NetMsgType::TX);
186 case MSG_BLOCK: return cmd.append(NetMsgType::BLOCK);
187 case MSG_FILTERED_BLOCK: return cmd.append(NetMsgType::MERKLEBLOCK);
188 case MSG_CMPCT_BLOCK: return cmd.append(NetMsgType::CMPCTBLOCK);
189 default:
190 throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
191 }
192 }
193
ToString() const194 std::string CInv::ToString() const
195 {
196 try {
197 return strprintf("%s %s", GetCommand(), hash.ToString());
198 } catch(const std::out_of_range &) {
199 return strprintf("0x%08x %s", type, hash.ToString());
200 }
201 }
202
getAllNetMessageTypes()203 const std::vector<std::string> &getAllNetMessageTypes()
204 {
205 return allNetMessageTypesVec;
206 }
207