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