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