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