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