Projects : bitcoin : bitcoin_dumpblock_no_losers
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 |
12 | bool Lookup(const char *pszName, std::vector<CAddress>& vaddr, int nServices, int nMaxSolutions, int portDefault = 0, bool fAllowPort = false); |
13 | bool Lookup(const char *pszName, CAddress& addr, int nServices, int portDefault = 0, bool fAllowPort = false); |
14 | |
15 | static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; |
16 | static const char* ppszTypeName[] = |
17 | { |
18 | "ERROR", |
19 | "tx", |
20 | "block", |
21 | }; |
22 | |
23 | CMessageHeader::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 | |
32 | CMessageHeader::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 | |
40 | std::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 | |
48 | bool 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 | |
78 | CAddress::CAddress() |
79 | { |
80 | Init(); |
81 | } |
82 | |
83 | CAddress::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 | |
91 | CAddress::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 | |
99 | CAddress::CAddress(const char* pszIn, int portIn, uint64 nServicesIn) |
100 | { |
101 | Init(); |
102 | Lookup(pszIn, *this, nServicesIn, portIn); |
103 | } |
104 | |
105 | CAddress::CAddress(const char* pszIn, uint64 nServicesIn) |
106 | { |
107 | Init(); |
108 | Lookup(pszIn, *this, nServicesIn, 0, true); |
109 | } |
110 | |
111 | CAddress::CAddress(std::string strIn, int portIn, uint64 nServicesIn) |
112 | { |
113 | Init(); |
114 | Lookup(strIn.c_str(), *this, nServicesIn, portIn); |
115 | } |
116 | |
117 | CAddress::CAddress(std::string strIn, uint64 nServicesIn) |
118 | { |
119 | Init(); |
120 | Lookup(strIn.c_str(), *this, nServicesIn, 0, true); |
121 | } |
122 | |
123 | void 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 | |
133 | bool 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 | |
140 | bool operator!=(const CAddress& a, const CAddress& b) |
141 | { |
142 | return (!(a == b)); |
143 | } |
144 | |
145 | bool 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 | |
160 | std::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 | |
169 | struct 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 | |
179 | bool CAddress::IsIPv4() const |
180 | { |
181 | return (memcmp(pchReserved, pchIPv4, sizeof(pchIPv4)) == 0); |
182 | } |
183 | |
184 | bool 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 | |
192 | bool CAddress::IsRFC3927() const |
193 | { |
194 | return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254); |
195 | } |
196 | |
197 | bool CAddress::IsLocal() const |
198 | { |
199 | return IsIPv4() && (GetByte(3) == 127 || |
200 | GetByte(3) == 0); |
201 | } |
202 | |
203 | bool CAddress::IsRoutable() const |
204 | { |
205 | return IsValid() && |
206 | !(IsRFC1918() || IsRFC3927() || IsLocal()); |
207 | } |
208 | |
209 | bool 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 | |
223 | unsigned char CAddress::GetByte(int n) const |
224 | { |
225 | return ((unsigned char*)&ip)[3-n]; |
226 | } |
227 | |
228 | std::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 | |
233 | std::string CAddress::ToStringIP() const |
234 | { |
235 | return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0)); |
236 | } |
237 | |
238 | std::string CAddress::ToStringPort() const |
239 | { |
240 | return strprintf("%u", ntohs(port)); |
241 | } |
242 | |
243 | std::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 | |
248 | void CAddress::print() const |
249 | { |
250 | printf("CAddress(%s)\n", ToString().c_str()); |
251 | } |
252 | |
253 | CInv::CInv() |
254 | { |
255 | type = 0; |
256 | hash = 0; |
257 | } |
258 | |
259 | CInv::CInv(int typeIn, const uint256& hashIn) |
260 | { |
261 | type = typeIn; |
262 | hash = hashIn; |
263 | } |
264 | |
265 | CInv::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 | |
281 | bool operator<(const CInv& a, const CInv& b) |
282 | { |
283 | return (a.type < b.type || (a.type == b.type && a.hash < b.hash)); |
284 | } |
285 | |
286 | bool CInv::IsKnownType() const |
287 | { |
288 | return (type >= 1 && type < ARRAYLEN(ppszTypeName)); |
289 | } |
290 | |
291 | const 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 | |
298 | std::string CInv::ToString() const |
299 | { |
300 | return strprintf("%s %s", GetCommand(), hash.ToString().c_str()); |
301 | } |
302 | |
303 | void CInv::print() const |
304 | { |
305 | printf("CInv(%s)\n", ToString().c_str()); |
306 | } |