Projects : bitcoin : bitcoin_dumpblock_no_losers

bitcoin/src/protocol.cpp

Dir - Raw

1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2011 The Bitcoin developers
3// Distributed under the MIT/X11 software license, see the accompanying
4// file license.txt or http://www.opensource.org/licenses/mit-license.php.
5
6#include "protocol.h"
7#include "util.h"
8#include <arpa/inet.h>
9
10
11// Prototypes from net.h, but that header (currently) stinks, can't #include it without breaking things
12bool Lookup(const char *pszName, std::vector<CAddress>& vaddr, int nServices, int nMaxSolutions, int portDefault = 0, bool fAllowPort = false);
13bool Lookup(const char *pszName, CAddress& addr, int nServices, int portDefault = 0, bool fAllowPort = false);
14
15static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
16static const char* ppszTypeName[] =
17{
18 "ERROR",
19 "tx",
20 "block",
21};
22
23CMessageHeader::CMessageHeader()
24{
25 memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
26 memset(pchCommand, 0, sizeof(pchCommand));
27 pchCommand[1] = 1;
28 nMessageSize = -1;
29 nChecksum = 0;
30}
31
32CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
33{
34 memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
35 strncpy(pchCommand, pszCommand, COMMAND_SIZE);
36 nMessageSize = nMessageSizeIn;
37 nChecksum = 0;
38}
39
40std::string CMessageHeader::GetCommand() const
41{
42 if (pchCommand[COMMAND_SIZE-1] == 0)
43 return std::string(pchCommand, pchCommand + strlen(pchCommand));
44 else
45 return std::string(pchCommand, pchCommand + COMMAND_SIZE);
46}
47
48bool CMessageHeader::IsValid() const
49{
50 // Check start string
51 if (memcmp(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)) != 0)
52 return false;
53
54 // Check the command string for errors
55 for (const char* p1 = pchCommand; p1 < pchCommand + COMMAND_SIZE; p1++)
56 {
57 if (*p1 == 0)
58 {
59 // Must be all zeros after the first zero
60 for (; p1 < pchCommand + COMMAND_SIZE; p1++)
61 if (*p1 != 0)
62 return false;
63 }
64 else if (*p1 < ' ' || *p1 > 0x7E)
65 return false;
66 }
67
68 // Message size
69 if (nMessageSize > MAX_SIZE)
70 {
71 printf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand().c_str(), nMessageSize);
72 return false;
73 }
74
75 return true;
76}
77
78CAddress::CAddress()
79{
80 Init();
81}
82
83CAddress::CAddress(unsigned int ipIn, unsigned short portIn, uint64 nServicesIn)
84{
85 Init();
86 ip = ipIn;
87 port = htons(portIn == 0 ? GetDefaultPort() : portIn);
88 nServices = nServicesIn;
89}
90
91CAddress::CAddress(const struct sockaddr_in& sockaddr, uint64 nServicesIn)
92{
93 Init();
94 ip = sockaddr.sin_addr.s_addr;
95 port = sockaddr.sin_port;
96 nServices = nServicesIn;
97}
98
99CAddress::CAddress(const char* pszIn, int portIn, uint64 nServicesIn)
100{
101 Init();
102 Lookup(pszIn, *this, nServicesIn, portIn);
103}
104
105CAddress::CAddress(const char* pszIn, uint64 nServicesIn)
106{
107 Init();
108 Lookup(pszIn, *this, nServicesIn, 0, true);
109}
110
111CAddress::CAddress(std::string strIn, int portIn, uint64 nServicesIn)
112{
113 Init();
114 Lookup(strIn.c_str(), *this, nServicesIn, portIn);
115}
116
117CAddress::CAddress(std::string strIn, uint64 nServicesIn)
118{
119 Init();
120 Lookup(strIn.c_str(), *this, nServicesIn, 0, true);
121}
122
123void CAddress::Init()
124{
125 nServices = NODE_NETWORK;
126 memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
127 ip = INADDR_NONE;
128 port = htons(GetDefaultPort());
129 nTime = 100000000;
130 nLastTry = 0;
131}
132
133bool operator==(const CAddress& a, const CAddress& b)
134{
135 return (memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved)) == 0 &&
136 a.ip == b.ip &&
137 a.port == b.port);
138}
139
140bool operator!=(const CAddress& a, const CAddress& b)
141{
142 return (!(a == b));
143}
144
145bool operator<(const CAddress& a, const CAddress& b)
146{
147 int ret = memcmp(a.pchReserved, b.pchReserved, sizeof(a.pchReserved));
148 if (ret < 0)
149 return true;
150 else if (ret == 0)
151 {
152 if (ntohl(a.ip) < ntohl(b.ip))
153 return true;
154 else if (a.ip == b.ip)
155 return ntohs(a.port) < ntohs(b.port);
156 }
157 return false;
158}
159
160std::vector<unsigned char> CAddress::GetKey() const
161{
162 CDataStream ss;
163 ss.reserve(18);
164 ss << FLATDATA(pchReserved) << ip << port;
165
166 return std::vector<unsigned char>(ss.begin(), ss.end());
167}
168
169struct sockaddr_in CAddress::GetSockAddr() const
170{
171 struct sockaddr_in sockaddr;
172 memset(&sockaddr, 0, sizeof(sockaddr));
173 sockaddr.sin_family = AF_INET;
174 sockaddr.sin_addr.s_addr = ip;
175 sockaddr.sin_port = port;
176 return sockaddr;
177}
178
179bool CAddress::IsIPv4() const
180{
181 return (memcmp(pchReserved, pchIPv4, sizeof(pchIPv4)) == 0);
182}
183
184bool CAddress::IsRFC1918() const
185{
186 return IsIPv4() && (GetByte(3) == 10 ||
187 (GetByte(3) == 192 && GetByte(2) == 168) ||
188 (GetByte(3) == 172 &&
189 (GetByte(2) >= 16 && GetByte(2) <= 31)));
190}
191
192bool CAddress::IsRFC3927() const
193{
194 return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
195}
196
197bool CAddress::IsLocal() const
198{
199 return IsIPv4() && (GetByte(3) == 127 ||
200 GetByte(3) == 0);
201}
202
203bool CAddress::IsRoutable() const
204{
205 return IsValid() &&
206 !(IsRFC1918() || IsRFC3927() || IsLocal());
207}
208
209bool CAddress::IsValid() const
210{
211 // Clean up 3-byte shifted addresses caused by garbage in size field
212 // of addr messages from versions before 0.2.9 checksum.
213 // Two consecutive addr messages look like this:
214 // header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
215 // so if the first length field is garbled, it reads the second batch
216 // of addr misaligned by 3 bytes.
217 if (memcmp(pchReserved, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
218 return false;
219
220 return (ip != 0 && ip != INADDR_NONE && port != htons(USHRT_MAX));
221}
222
223unsigned char CAddress::GetByte(int n) const
224{
225 return ((unsigned char*)&ip)[3-n];
226}
227
228std::string CAddress::ToStringIPPort() const
229{
230 return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
231}
232
233std::string CAddress::ToStringIP() const
234{
235 return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
236}
237
238std::string CAddress::ToStringPort() const
239{
240 return strprintf("%u", ntohs(port));
241}
242
243std::string CAddress::ToString() const
244{
245 return strprintf("%u.%u.%u.%u:%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0), ntohs(port));
246}
247
248void CAddress::print() const
249{
250 printf("CAddress(%s)\n", ToString().c_str());
251}
252
253CInv::CInv()
254{
255 type = 0;
256 hash = 0;
257}
258
259CInv::CInv(int typeIn, const uint256& hashIn)
260{
261 type = typeIn;
262 hash = hashIn;
263}
264
265CInv::CInv(const std::string& strType, const uint256& hashIn)
266{
267 int i;
268 for (i = 1; i < ARRAYLEN(ppszTypeName); i++)
269 {
270 if (strType == ppszTypeName[i])
271 {
272 type = i;
273 break;
274 }
275 }
276 if (i == ARRAYLEN(ppszTypeName))
277 throw std::out_of_range(strprintf("CInv::CInv(string, uint256) : unknown type '%s'", strType.c_str()));
278 hash = hashIn;
279}
280
281bool operator<(const CInv& a, const CInv& b)
282{
283 return (a.type < b.type || (a.type == b.type && a.hash < b.hash));
284}
285
286bool CInv::IsKnownType() const
287{
288 return (type >= 1 && type < ARRAYLEN(ppszTypeName));
289}
290
291const char* CInv::GetCommand() const
292{
293 if (!IsKnownType())
294 throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type));
295 return ppszTypeName[type];
296}
297
298std::string CInv::ToString() const
299{
300 return strprintf("%s %s", GetCommand(), hash.ToString().c_str());
301}
302
303void CInv::print() const
304{
305 printf("CInv(%s)\n", ToString().c_str());
306}