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 *REJECT="reject";
38 const char *SENDHEADERS="sendheaders";
39 const char *FEEFILTER="feefilter";
40 const char *SENDCMPCT="sendcmpct";
41 const char *CMPCTBLOCK="cmpctblock";
42 const char *GETBLOCKTXN="getblocktxn";
43 const char *BLOCKTXN="blocktxn";
44 } // namespace NetMsgType
45
46 /** All known message types. Keep this in the same order as the list of
47 * messages above and in protocol.h.
48 */
49 const static std::string allNetMessageTypes[] = {
50 NetMsgType::VERSION,
51 NetMsgType::VERACK,
52 NetMsgType::ADDR,
53 NetMsgType::INV,
54 NetMsgType::GETDATA,
55 NetMsgType::MERKLEBLOCK,
56 NetMsgType::GETBLOCKS,
57 NetMsgType::GETHEADERS,
58 NetMsgType::TX,
59 NetMsgType::HEADERS,
60 NetMsgType::BLOCK,
61 NetMsgType::GETADDR,
62 NetMsgType::MEMPOOL,
63 NetMsgType::PING,
64 NetMsgType::PONG,
65 NetMsgType::NOTFOUND,
66 NetMsgType::FILTERLOAD,
67 NetMsgType::FILTERADD,
68 NetMsgType::FILTERCLEAR,
69 NetMsgType::REJECT,
70 NetMsgType::SENDHEADERS,
71 NetMsgType::FEEFILTER,
72 NetMsgType::SENDCMPCT,
73 NetMsgType::CMPCTBLOCK,
74 NetMsgType::GETBLOCKTXN,
75 NetMsgType::BLOCKTXN,
76 };
77 const static std::vector<std::string> allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes));
78
CMessageHeader(const MessageStartChars & pchMessageStartIn)79 CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn)
80 {
81 memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
82 memset(pchCommand, 0, sizeof(pchCommand));
83 nMessageSize = -1;
84 memset(pchChecksum, 0, CHECKSUM_SIZE);
85 }
86
CMessageHeader(const MessageStartChars & pchMessageStartIn,const char * pszCommand,unsigned int nMessageSizeIn)87 CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn, const char* pszCommand, unsigned int nMessageSizeIn)
88 {
89 memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
90 memset(pchCommand, 0, sizeof(pchCommand));
91 strncpy(pchCommand, pszCommand, COMMAND_SIZE);
92 nMessageSize = nMessageSizeIn;
93 memset(pchChecksum, 0, CHECKSUM_SIZE);
94 }
95
GetCommand() const96 std::string CMessageHeader::GetCommand() const
97 {
98 return std::string(pchCommand, pchCommand + strnlen(pchCommand, COMMAND_SIZE));
99 }
100
IsValid(const MessageStartChars & pchMessageStartIn) const101 bool CMessageHeader::IsValid(const MessageStartChars& pchMessageStartIn) const
102 {
103 // Check start string
104 if (memcmp(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE) != 0)
105 return false;
106
107 // Check the command string for errors
108 for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
109 {
110 if (*p1 == 0)
111 {
112 // Must be all zeros after the first zero
113 for (; p1 < pchCommand + COMMAND_SIZE; p1++)
114 if (*p1 != 0)
115 return false;
116 }
117 else if (*p1 < ' ' || *p1 > 0x7E)
118 return false;
119 }
120
121 // Message size
122 if (nMessageSize > MAX_SIZE)
123 {
124 LogPrintf("CMessageHeader::IsValid(): (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand(), nMessageSize);
125 return false;
126 }
127
128 return true;
129 }
130
131
GetDesirableServiceFlags(ServiceFlags services)132 ServiceFlags GetDesirableServiceFlags(ServiceFlags services) {
133 if ((services & NODE_NETWORK_LIMITED) && g_initial_block_download_completed) {
134 return ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS);
135 }
136 return ServiceFlags(NODE_NETWORK | NODE_WITNESS);
137 }
138
SetServiceFlagsIBDCache(bool state)139 void SetServiceFlagsIBDCache(bool state) {
140 g_initial_block_download_completed = state;
141 }
142
143
CAddress()144 CAddress::CAddress() : CService()
145 {
146 Init();
147 }
148
CAddress(CService ipIn,ServiceFlags nServicesIn)149 CAddress::CAddress(CService ipIn, ServiceFlags nServicesIn) : CService(ipIn)
150 {
151 Init();
152 nServices = nServicesIn;
153 }
154
Init()155 void CAddress::Init()
156 {
157 nServices = NODE_NONE;
158 nTime = 100000000;
159 }
160
CInv()161 CInv::CInv()
162 {
163 type = 0;
164 hash.SetNull();
165 }
166
CInv(int typeIn,const uint256 & hashIn)167 CInv::CInv(int typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {}
168
operator <(const CInv & a,const CInv & b)169 bool operator<(const CInv& a, const CInv& b)
170 {
171 return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
172 }
173
GetCommand() const174 std::string CInv::GetCommand() const
175 {
176 std::string cmd;
177 if (type & MSG_WITNESS_FLAG)
178 cmd.append("witness-");
179 int masked = type & MSG_TYPE_MASK;
180 switch (masked)
181 {
182 case MSG_TX: return cmd.append(NetMsgType::TX);
183 case MSG_BLOCK: return cmd.append(NetMsgType::BLOCK);
184 case MSG_FILTERED_BLOCK: return cmd.append(NetMsgType::MERKLEBLOCK);
185 case MSG_CMPCT_BLOCK: return cmd.append(NetMsgType::CMPCTBLOCK);
186 default:
187 throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type));
188 }
189 }
190
ToString() const191 std::string CInv::ToString() const
192 {
193 try {
194 return strprintf("%s %s", GetCommand(), hash.ToString());
195 } catch(const std::out_of_range &) {
196 return strprintf("0x%08x %s", type, hash.ToString());
197 }
198 }
199
getAllNetMessageTypes()200 const std::vector<std::string> &getAllNetMessageTypes()
201 {
202 return allNetMessageTypesVec;
203 }
204