Browse Source

IPv6/AAAA record support

pull/1/head
Pieter Wuille 12 years ago
parent
commit
309d8ee0ae
  1. 6
      Makefile
  2. 12
      bitcoin.cpp
  3. 2
      bitcoin.h
  4. 18
      db.cpp
  5. 35
      db.h
  6. 28
      dns.c
  7. 10
      dns.h
  8. 62
      main.cpp
  9. 827
      netbase.cpp
  10. 123
      netbase.h
  11. 4
      protocol.cpp
  12. 6
      protocol.h
  13. 6
      test.pl
  14. 44
      util.h

6
Makefile

@ -1,8 +1,8 @@
dnsseed: dns.o bitcoin.o netbase.o protocol.o db.o main.o dnsseed: dns.o bitcoin.o netbase.o protocol.o db.o main.o util.o
g++ -pthread -lcrypto -o dnsseed dns.o bitcoin.o netbase.o protocol.o db.o main.o g++ -pthread -o dnsseed dns.o bitcoin.o netbase.o protocol.o db.o main.o util.o -lcrypto
%.o: %.cpp bitcoin.h netbase.h protocol.h db.h serialize.h uint256.h util.h %.o: %.cpp bitcoin.h netbase.h protocol.h db.h serialize.h uint256.h util.h
g++ -pthread -O2 -ggdb3 -march=nocona -Wno-invalid-offsetof -c -o $@ $< g++ -DUSE_IPV6 -pthread -O2 -ggdb3 -march=nocona -Wno-invalid-offsetof -c -o $@ $<
dns.o: dns.c dns.o: dns.c
gcc -pthread -std=c99 -O2 -ggdb3 -march=nocona dns.c -c -o dns.o gcc -pthread -std=c99 -O2 -ggdb3 -march=nocona dns.c -c -o dns.o

12
bitcoin.cpp

@ -72,7 +72,7 @@ class CNode {
int64 nTime = time(NULL); int64 nTime = time(NULL);
uint64 nLocalNonce = BITCOIN_SEED_NONCE; uint64 nLocalNonce = BITCOIN_SEED_NONCE;
int64 nLocalServices = 0; int64 nLocalServices = 0;
CAddress me(CIPPort("0.0.0.0")); CAddress me(CService("0.0.0.0"));
BeginMessage("version"); BeginMessage("version");
int nBestHeight = REQUIRE_HEIGHT; int nBestHeight = REQUIRE_HEIGHT;
string ver = "/bitcoin-seeder:0.01/"; string ver = "/bitcoin-seeder:0.01/";
@ -132,8 +132,6 @@ class CNode {
CAddress &addr = *it; CAddress &addr = *it;
// printf("%s: got address %s\n", ToString(you).c_str(), addr.ToString().c_str(), (int)(vAddr->size())); // printf("%s: got address %s\n", ToString(you).c_str(), addr.ToString().c_str(), (int)(vAddr->size()));
it++; it++;
if (!addr.IsIPv4())
continue;
if (addr.nTime <= 100000000 || addr.nTime > now + 600) if (addr.nTime <= 100000000 || addr.nTime > now + 600)
addr.nTime = now - 5 * 86400; addr.nTime = now - 5 * 86400;
vAddr->push_back(addr); vAddr->push_back(addr);
@ -192,7 +190,7 @@ class CNode {
} }
public: public:
CNode(const CIPPort& ip, vector<CAddress>& vAddrIn) : you(ip), nHeaderStart(-1), nMessageStart(-1), vAddr(&vAddrIn), ban(0), doneAfter(0), nVersion(0) { CNode(const CService& ip, vector<CAddress>& vAddrIn) : you(ip), nHeaderStart(-1), nMessageStart(-1), vAddr(&vAddrIn), ban(0), doneAfter(0), nVersion(0) {
vSend.SetType(SER_NETWORK); vSend.SetType(SER_NETWORK);
vSend.SetVersion(0); vSend.SetVersion(0);
vRecv.SetType(SER_NETWORK); vRecv.SetType(SER_NETWORK);
@ -204,7 +202,7 @@ public:
} }
bool Run() { bool Run() {
bool res = true; bool res = true;
if (!you.ConnectSocket(sock)) return false; if (!ConnectSocket(you, sock)) return false;
PushVersion(); PushVersion();
Send(); Send();
int64 now; int64 now;
@ -262,7 +260,7 @@ public:
} }
}; };
bool TestNode(const CIPPort &cip, int &ban, int &clientV, std::string &clientSV, vector<CAddress>& vAddr) { bool TestNode(const CService &cip, int &ban, int &clientV, std::string &clientSV, vector<CAddress>& vAddr) {
try { try {
CNode node(cip, vAddr); CNode node(cip, vAddr);
bool ret = node.Run(); bool ret = node.Run();
@ -283,7 +281,7 @@ bool TestNode(const CIPPort &cip, int &ban, int &clientV, std::string &clientSV,
/* /*
int main(void) { int main(void) {
CIPPort ip("bitcoin.sipa.be", 8333, true); CService ip("bitcoin.sipa.be", 8333, true);
vector<CAddress> vAddr; vector<CAddress> vAddr;
vAddr.clear(); vAddr.clear();
int ban = 0; int ban = 0;

2
bitcoin.h

@ -3,6 +3,6 @@
#include "protocol.h" #include "protocol.h"
bool TestNode(const CIPPort &cip, int &ban, int &client, std::string &clientSV, std::vector<CAddress>& vAddr); bool TestNode(const CService &cip, int &ban, int &client, std::string &clientSV, std::vector<CAddress>& vAddr);
#endif #endif

18
db.cpp

@ -26,7 +26,7 @@ void CAddrInfo::Update(bool good) {
// 100.0 * stat1W.reliability, 100.0 * (stat1W.reliability + 1.0 - stat1W.weight), stat1W.count); // 100.0 * stat1W.reliability, 100.0 * (stat1W.reliability + 1.0 - stat1W.weight), stat1W.count);
} }
bool CAddrDb::Get_(CIPPort &ip, int &wait) { bool CAddrDb::Get_(CService &ip, int &wait) {
int64 now = time(NULL); int64 now = time(NULL);
int cont = 0; int cont = 0;
int tot = unkId.size(); int tot = unkId.size();
@ -78,13 +78,13 @@ bool CAddrDb::Get_(CIPPort &ip, int &wait) {
return true; return true;
} }
int CAddrDb::Lookup_(const CIPPort &ip) { int CAddrDb::Lookup_(const CService &ip) {
if (ipToId.count(ip)) if (ipToId.count(ip))
return ipToId[ip]; return ipToId[ip];
return -1; return -1;
} }
void CAddrDb::Good_(const CIPPort &addr, int clientV, std::string clientSV) { void CAddrDb::Good_(const CService &addr, int clientV, std::string clientSV) {
int id = Lookup_(addr); int id = Lookup_(addr);
if (id == -1) return; if (id == -1) return;
unkId.erase(id); unkId.erase(id);
@ -101,7 +101,7 @@ void CAddrDb::Good_(const CIPPort &addr, int clientV, std::string clientSV) {
ourId.push_back(id); ourId.push_back(id);
} }
void CAddrDb::Bad_(const CIPPort &addr, int ban) void CAddrDb::Bad_(const CService &addr, int ban)
{ {
int id = Lookup_(addr); int id = Lookup_(addr);
if (id == -1) return; if (id == -1) return;
@ -130,7 +130,7 @@ void CAddrDb::Bad_(const CIPPort &addr, int ban)
nDirty++; nDirty++;
} }
void CAddrDb::Skipped_(const CIPPort &addr) void CAddrDb::Skipped_(const CService &addr)
{ {
int id = Lookup_(addr); int id = Lookup_(addr);
if (id == -1) return; if (id == -1) return;
@ -144,7 +144,7 @@ void CAddrDb::Skipped_(const CIPPort &addr)
void CAddrDb::Add_(const CAddress &addr, bool force) { void CAddrDb::Add_(const CAddress &addr, bool force) {
if (!force && !addr.IsRoutable()) if (!force && !addr.IsRoutable())
return; return;
CIPPort ipp(addr); CService ipp(addr);
if (banned.count(ipp)) { if (banned.count(ipp)) {
time_t bantime = banned[ipp]; time_t bantime = banned[ipp];
if (force || (bantime < time(NULL) && addr.nTime > bantime)) if (force || (bantime < time(NULL) && addr.nTime > bantime))
@ -180,7 +180,7 @@ void CAddrDb::Add_(const CAddress &addr, bool force) {
nDirty++; nDirty++;
} }
void CAddrDb::GetIPs_(set<CIP>& ips, int max, bool fOnlyIPv4) { void CAddrDb::GetIPs_(set<CNetAddr>& ips, int max, const bool* nets) {
if (goodId.size() == 0) { if (goodId.size() == 0) {
int id = -1; int id = -1;
if (ourId.size() == 0) { if (ourId.size() == 0) {
@ -208,8 +208,8 @@ void CAddrDb::GetIPs_(set<CIP>& ips, int max, bool fOnlyIPv4) {
ids.insert(id); ids.insert(id);
} }
for (set<int>::const_iterator it = ids.begin(); it != ids.end(); it++) { for (set<int>::const_iterator it = ids.begin(); it != ids.end(); it++) {
CIPPort &ip = idToInfo[*it].ip; CService &ip = idToInfo[*it].ip;
if (ip.IsValid() && (!fOnlyIPv4 || ip.IsIPv4())) if (nets[ip.GetNetwork()])
ips.insert(ip); ips.insert(ip);
} }
} }

35
db.h

@ -12,7 +12,7 @@
#define MIN_RETRY 1000 #define MIN_RETRY 1000
std::string static inline ToString(const CIPPort &ip) { std::string static inline ToString(const CService &ip) {
std::string str = ip.ToString(); std::string str = ip.ToString();
while (str.size() < 22) str += ' '; while (str.size() < 22) str += ' ';
return str; return str;
@ -44,7 +44,7 @@ public:
class CAddrReport { class CAddrReport {
public: public:
CIPPort ip; CService ip;
int clientVersion; int clientVersion;
double uptime[5]; double uptime[5];
std::string clientSubVersion; std::string clientSubVersion;
@ -53,7 +53,7 @@ public:
class CAddrInfo { class CAddrInfo {
private: private:
CIPPort ip; CService ip;
uint64_t services; uint64_t services;
int64 lastTry; int64 lastTry;
int64 ourLastTry; int64 ourLastTry;
@ -87,7 +87,6 @@ public:
if (ip.GetPort() != 8333) return false; if (ip.GetPort() != 8333) return false;
if (!(services & NODE_NETWORK)) return false; if (!(services & NODE_NETWORK)) return false;
if (!ip.IsRoutable()) return false; if (!ip.IsRoutable()) return false;
if (!ip.IsIPv4()) return false;
if (clientVersion && clientVersion < 32400) return false; if (clientVersion && clientVersion < 32400) return false;
if (total <= 3 && success * 2 >= total) return true; if (total <= 3 && success * 2 >= total) return true;
@ -170,7 +169,7 @@ private:
mutable CCriticalSection cs; mutable CCriticalSection cs;
int nId; // number of address id's int nId; // number of address id's
std::map<int, CAddrInfo> idToInfo; // map address id to address info (b,c,d,e) std::map<int, CAddrInfo> idToInfo; // map address id to address info (b,c,d,e)
std::map<CIPPort, int> ipToId; // map ip to id (b,c,d,e) std::map<CService, int> ipToId; // map ip to id (b,c,d,e)
std::deque<int> ourId; // sequence of tried nodes, in order we have tried connecting to them (c,d) std::deque<int> ourId; // sequence of tried nodes, in order we have tried connecting to them (c,d)
std::set<int> unkId; // set of nodes not yet tried (b) std::set<int> unkId; // set of nodes not yet tried (b)
std::set<int> goodId; // set of good nodes (d, good e) std::set<int> goodId; // set of good nodes (d, good e)
@ -179,15 +178,15 @@ private:
protected: protected:
// internal routines that assume proper locks are acquired // internal routines that assume proper locks are acquired
void Add_(const CAddress &addr, bool force); // add an address void Add_(const CAddress &addr, bool force); // add an address
bool Get_(CIPPort &ip, int& wait); // get an IP to test (must call Good_, Bad_, or Skipped_ on result afterwards) bool Get_(CService &ip, int& wait); // get an IP to test (must call Good_, Bad_, or Skipped_ on result afterwards)
void Good_(const CIPPort &ip, int clientV, std::string clientSV); // mark an IP as good (must have been returned by Get_) void Good_(const CService &ip, int clientV, std::string clientSV); // mark an IP as good (must have been returned by Get_)
void Bad_(const CIPPort &ip, int ban); // mark an IP as bad (and optionally ban it) (must have been returned by Get_) void Bad_(const CService &ip, int ban); // mark an IP as bad (and optionally ban it) (must have been returned by Get_)
void Skipped_(const CIPPort &ip); // mark an IP as skipped (must have been returned by Get_) void Skipped_(const CService &ip); // mark an IP as skipped (must have been returned by Get_)
int Lookup_(const CIPPort &ip); // look up id of an IP int Lookup_(const CService &ip); // look up id of an IP
void GetIPs_(std::set<CIP>& ips, int max, bool fOnlyIPv4); // get a random set of IPs (shared lock only) void GetIPs_(std::set<CNetAddr>& ips, int max, const bool* nets); // get a random set of IPs (shared lock only)
public: public:
std::map<CIPPort, time_t> banned; // nodes that are banned, with their unban time (a) std::map<CService, time_t> banned; // nodes that are banned, with their unban time (a)
void GetStats(CAddrDbStats &stats) { void GetStats(CAddrDbStats &stats) {
SHARED_CRITICAL_BLOCK(cs) { SHARED_CRITICAL_BLOCK(cs) {
@ -272,24 +271,24 @@ public:
for (int i=0; i<vAddr.size(); i++) for (int i=0; i<vAddr.size(); i++)
Add_(vAddr[i], fForce); Add_(vAddr[i], fForce);
} }
void Good(const CIPPort &addr, int clientVersion, std::string clientSubVersion) { void Good(const CService &addr, int clientVersion, std::string clientSubVersion) {
CRITICAL_BLOCK(cs) CRITICAL_BLOCK(cs)
Good_(addr, clientVersion, clientSubVersion); Good_(addr, clientVersion, clientSubVersion);
} }
void Skipped(const CIPPort &addr) { void Skipped(const CService &addr) {
CRITICAL_BLOCK(cs) CRITICAL_BLOCK(cs)
Skipped_(addr); Skipped_(addr);
} }
void Bad(const CIPPort &addr, int ban = 0) { void Bad(const CService &addr, int ban = 0) {
CRITICAL_BLOCK(cs) CRITICAL_BLOCK(cs)
Bad_(addr, ban); Bad_(addr, ban);
} }
bool Get(CIPPort &ip, int& wait) { bool Get(CService &ip, int& wait) {
CRITICAL_BLOCK(cs) CRITICAL_BLOCK(cs)
return Get_(ip, wait); return Get_(ip, wait);
} }
void GetIPs(std::set<CIP>& ips, int max, bool fOnlyIPv4 = true) { void GetIPs(std::set<CNetAddr>& ips, int max, const bool *nets) {
SHARED_CRITICAL_BLOCK(cs) SHARED_CRITICAL_BLOCK(cs)
GetIPs_(ips, max, fOnlyIPv4); GetIPs_(ips, max, nets);
} }
}; };

28
dns.c

@ -127,7 +127,9 @@ error:
} }
int static write_record_a(unsigned char** outpos, const unsigned char *outend, const char *name, int offset, dns_class cls, int ttl, const struct in_addr *ip) { int static write_record_a(unsigned char** outpos, const unsigned char *outend, const char *name, int offset, dns_class cls, int ttl, const addr_t *ip) {
if (ip->v != 4)
return -6;
unsigned char *oldpos = *outpos; unsigned char *oldpos = *outpos;
int error = 0; int error = 0;
int ret = write_record(outpos, outend, name, offset, TYPE_A, cls, ttl); int ret = write_record(outpos, outend, name, offset, TYPE_A, cls, ttl);
@ -136,16 +138,17 @@ int static write_record_a(unsigned char** outpos, const unsigned char *outend, c
// rdlength // rdlength
*((*outpos)++) = 0; *((*outpos)++) = 4; *((*outpos)++) = 0; *((*outpos)++) = 4;
// rdata // rdata
const unsigned char *pd = (const unsigned char*)ip;
for (int i=0; i<4; i++) for (int i=0; i<4; i++)
*((*outpos)++) = pd[i]; *((*outpos)++) = ip->data.v4[i];
return 0; return 0;
error: error:
*outpos = oldpos; *outpos = oldpos;
return error; return error;
} }
int static write_record_aaaa(unsigned char** outpos, const unsigned char *outend, const char *name, int offset, dns_class cls, int ttl, const struct in6_addr *ip) { int static write_record_aaaa(unsigned char** outpos, const unsigned char *outend, const char *name, int offset, dns_class cls, int ttl, const addr_t *ip) {
if (ip->v != 6)
return -6;
unsigned char *oldpos = *outpos; unsigned char *oldpos = *outpos;
int error = 0; int error = 0;
int ret = write_record(outpos, outend, name, offset, TYPE_AAAA, cls, ttl); int ret = write_record(outpos, outend, name, offset, TYPE_AAAA, cls, ttl);
@ -154,9 +157,8 @@ int static write_record_aaaa(unsigned char** outpos, const unsigned char *outend
// rdlength // rdlength
*((*outpos)++) = 0; *((*outpos)++) = 16; *((*outpos)++) = 0; *((*outpos)++) = 16;
// rdata // rdata
const unsigned char *pd = (const unsigned char*)ip;
for (int i=0; i<16; i++) for (int i=0; i<16; i++)
*((*outpos)++) = pd[i]; *((*outpos)++) = ip->data.v6[i];
return 0; return 0;
error: error:
*outpos = oldpos; *outpos = oldpos;
@ -293,13 +295,17 @@ ssize_t static dnshandle(dns_opt_t *opt, const unsigned char *inbuf, size_t insi
if (!ret2) { outbuf[7]++; } if (!ret2) { outbuf[7]++; }
} }
// A records // A/AAAA records
if ((typ == TYPE_A || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY)) { if ((typ == TYPE_A || typ == TYPE_AAAA || typ == QTYPE_ANY) && (cls == CLASS_IN || cls == QCLASS_ANY)) {
struct in_addr addr[32]; addr_t addr[32];
int naddr = opt->cb((void*)opt, addr, 32, 1); int naddr = opt->cb((void*)opt, addr, 32, typ == TYPE_A || typ == QTYPE_ANY, typ == TYPE_AAAA || typ == QTYPE_ANY);
int n = 0; int n = 0;
while (n < naddr) { while (n < naddr) {
int ret = write_record_a(&outpos, outend - auth_size, "", offset, CLASS_IN, opt->datattl, &addr[n]); int ret = 1;
if (addr->v == 4)
ret = write_record_a(&outpos, outend - auth_size, "", offset, CLASS_IN, opt->datattl, &addr[n]);
else if (addr->v == 6)
ret = write_record_aaaa(&outpos, outend - auth_size, "", offset, CLASS_IN, opt->datattl, &addr[n]);
// printf("wrote A record: %i\n", ret); // printf("wrote A record: %i\n", ret);
if (!ret) { if (!ret) {
n++; n++;

10
dns.h

@ -3,6 +3,14 @@
#include <stdint.h> #include <stdint.h>
typedef struct {
int v;
union {
unsigned char v4[4];
unsigned char v6[16];
} data;
} addr_t;
typedef struct { typedef struct {
int port; int port;
int datattl; int datattl;
@ -10,7 +18,7 @@ typedef struct {
const char *host; const char *host;
const char *ns; const char *ns;
const char *mbox; const char *mbox;
int (*cb)(void *opt, struct in_addr *addr, int max, int ipv4only); int (*cb)(void *opt, addr_t *addr, int max, int ipv4, int ipv6);
// stats // stats
uint64_t nRequests; uint64_t nRequests;
} dns_opt_t; } dns_opt_t;

62
main.cpp

@ -105,7 +105,7 @@ CAddrDb db;
extern "C" void* ThreadCrawler(void* data) { extern "C" void* ThreadCrawler(void* data) {
do { do {
CIPPort ip; CService ip;
int wait = 5; int wait = 5;
if (!db.Get(ip, wait)) { if (!db.Get(ip, wait)) {
wait *= 1000; wait *= 1000;
@ -127,29 +127,50 @@ extern "C" void* ThreadCrawler(void* data) {
} while(1); } while(1);
} }
extern "C" int GetIPList(void *thread, struct in_addr *addr, int max, int ipv4only); extern "C" int GetIPList(void *thread, addr_t *addr, int max, int ipv4, int ipv6);
class CDnsThread { class CDnsThread {
public: public:
dns_opt_t dns_opt; dns_opt_t dns_opt;
vector<struct in_addr> cache; vector<addr_t> cache;
int nIPv4, nIPv6;
time_t cacheTime; time_t cacheTime;
unsigned int cacheHits; unsigned int cacheHits;
uint64_t dbQueries; uint64_t dbQueries;
void cacheHit(int ipv4only, bool force = false) { void cacheHit(bool force = false) {
static bool nets[NET_MAX] = {};
if (!nets[NET_IPV4]) {
nets[NET_IPV4] = true;
nets[NET_IPV6] = true;
}
time_t now = time(NULL); time_t now = time(NULL);
cacheHits++; cacheHits++;
if (force || cacheHits > (cache.size()*cache.size()/400) || (cacheHits*cacheHits > cache.size() / 20 && (now - cacheTime > 5))) { if (force || cacheHits > (cache.size()*cache.size()/400) || (cacheHits*cacheHits > cache.size() / 20 && (now - cacheTime > 5))) {
set<CIP> ips; set<CNetAddr> ips;
db.GetIPs(ips, 1000, ipv4only); db.GetIPs(ips, 1000, nets);
dbQueries++; dbQueries++;
cache.clear(); cache.clear();
nIPv4 = 0;
nIPv6 = 0;
cache.reserve(ips.size()); cache.reserve(ips.size());
for (set<CIP>::iterator it = ips.begin(); it != ips.end(); it++) { for (set<CNetAddr>::iterator it = ips.begin(); it != ips.end(); it++) {
struct in_addr addr; struct in_addr addr;
struct in6_addr addr6;
if ((*it).GetInAddr(&addr)) { if ((*it).GetInAddr(&addr)) {
cache.push_back(addr); addr_t a;
a.v = 4;
memcpy(&a.data.v4, &addr, 4);
cache.push_back(a);
nIPv4++;
#ifdef USE_IPV6
} else if ((*it).GetIn6Addr(&addr6)) {
addr_t a;
a.v = 6;
memcpy(&a.data.v6, &addr6, 16);
cache.push_back(a);
nIPv6++;
#endif
} }
} }
cacheHits = 0; cacheHits = 0;
@ -171,7 +192,9 @@ public:
cacheTime = 0; cacheTime = 0;
cacheHits = 0; cacheHits = 0;
dbQueries = 0; dbQueries = 0;
cacheHit(true, true); nIPv4 = 0;
nIPv6 = 0;
cacheHit(true);
} }
void run() { void run() {
@ -179,14 +202,21 @@ public:
} }
}; };
extern "C" int GetIPList(void *data, struct in_addr *addr, int max, int ipv4only) { extern "C" int GetIPList(void *data, addr_t* addr, int max, int ipv4, int ipv6) {
CDnsThread *thread = (CDnsThread*)data; CDnsThread *thread = (CDnsThread*)data;
thread->cacheHit(ipv4only); thread->cacheHit();
unsigned int size = thread->cache.size(); unsigned int size = (ipv4 ? thread->nIPv4 : 0) + (ipv6 ? thread->nIPv6 : 0);
if (max > size) if (max > size)
max = size; max = size;
for (int i=0; i<max; i++) { int i=0;
while (i<max) {
int j = i + (rand() % (size - i)); int j = i + (rand() % (size - i));
do {
bool ok = (ipv4 && thread->cache[j].v == 4) ||
(ipv6 && thread->cache[j].v == 6);
if (ok) break;
j = i + ((j - i + 1) % (size - i));
} while(1);
addr[i] = thread->cache[j]; addr[i] = thread->cache[j];
thread->cache[j] = thread->cache[i]; thread->cache[j] = thread->cache[i];
thread->cache[i] = addr[i]; thread->cache[i] = addr[i];
@ -269,10 +299,10 @@ static const string seeds[] = {"dnsseed.bluematt.me", "bitseed.xf2.org", "dnssee
extern "C" void* ThreadSeeder(void*) { extern "C" void* ThreadSeeder(void*) {
do { do {
for (int i=0; i<sizeof(seeds)/sizeof(seeds[0]); i++) { for (int i=0; i<sizeof(seeds)/sizeof(seeds[0]); i++) {
vector<CIP> ips; vector<CNetAddr> ips;
LookupHost(seeds[i].c_str(), ips); LookupHost(seeds[i].c_str(), ips);
for (vector<CIP>::iterator it = ips.begin(); it != ips.end(); it++) { for (vector<CNetAddr>::iterator it = ips.begin(); it != ips.end(); it++) {
db.Add(CIPPort(*it, 8333), true); db.Add(CService(*it, 8333), true);
} }
} }
Sleep(1800000); Sleep(1800000);

827
netbase.cpp

File diff suppressed because it is too large Load Diff

123
netbase.h

@ -1,49 +1,52 @@
// Copyright (c) 2011 The Bitcoin developers // Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying // Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_NETBASE_H #ifndef BITCOIN_NETBASE_H
#define BITCOIN_NETBASE_H #define BITCOIN_NETBASE_H
#include <string> #include <string>
#include <vector> #include <vector>
#include "serialize.h"
#include "compat.h"
extern int nConnectTimeout;
#ifdef WIN32 #ifdef WIN32
#include <winsock2.h> // In MSVC, this is defined as a macro, undefine it to prevent a compile and link error
#include <mswsock.h> #undef SetPort
#include <ws2tcpip.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>
#include <ifaddrs.h>
#endif
#ifdef BSD
#include <netinet/in.h>
#endif #endif
#include "serialize.h" enum Network
{
NET_UNROUTABLE,
NET_IPV4,
NET_IPV6,
NET_TOR,
NET_I2P,
typedef int SOCKET; NET_MAX,
};
extern int nConnectTimeout; extern int nConnectTimeout;
extern bool fNameLookup;
// IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) /** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */
class CIP class CNetAddr
{ {
protected: protected:
unsigned char ip[16]; // in network byte order unsigned char ip[16]; // in network byte order
public: public:
CIP(); CNetAddr();
CIP(const struct in_addr& ipv4Addr); CNetAddr(const struct in_addr& ipv4Addr);
CIP(const char *pszIp, bool fAllowLookup = false); explicit CNetAddr(const char *pszIp, bool fAllowLookup = false);
CIP(const std::string &strIp, bool fAllowLookup = false); explicit CNetAddr(const std::string &strIp, bool fAllowLookup = false);
void Init(); void Init();
void SetIP(const CIP& ip); void SetIP(const CNetAddr& ip);
bool SetSpecial(const std::string &strName); // for Tor and I2P addresses
bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0) bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor/I2P)
bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12) bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32) bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16) bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
@ -54,25 +57,30 @@ class CIP
bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64) bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64)
bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96) bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96)
bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96)
bool IsTor() const;
bool IsI2P() const;
bool IsLocal() const; bool IsLocal() const;
bool IsRoutable() const; bool IsRoutable() const;
bool IsValid() const; bool IsValid() const;
bool IsMulticast() const; bool IsMulticast() const;
enum Network GetNetwork() const;
std::string ToString() const; std::string ToString() const;
std::string ToStringIP() const;
int GetByte(int n) const; int GetByte(int n) const;
int64 GetHash() const; int64 GetHash() const;
bool GetInAddr(struct in_addr* pipv4Addr) const; bool GetInAddr(struct in_addr* pipv4Addr) const;
std::vector<unsigned char> GetGroup() const; std::vector<unsigned char> GetGroup() const;
int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const;
void print() const; void print() const;
#ifdef USE_IPV6 #ifdef USE_IPV6
CIP(const struct in6_addr& pipv6Addr); CNetAddr(const struct in6_addr& pipv6Addr);
bool GetIn6Addr(struct in6_addr* pipv6Addr) const; bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
#endif #endif
friend bool operator==(const CIP& a, const CIP& b); friend bool operator==(const CNetAddr& a, const CNetAddr& b);
friend bool operator!=(const CIP& a, const CIP& b); friend bool operator!=(const CNetAddr& a, const CNetAddr& b);
friend bool operator<(const CIP& a, const CIP& b); friend bool operator<(const CNetAddr& a, const CNetAddr& b);
IMPLEMENT_SERIALIZE IMPLEMENT_SERIALIZE
( (
@ -80,41 +88,43 @@ class CIP
) )
}; };
class CIPPort : public CIP /** A combination of a network address (CNetAddr) and a (TCP) port */
class CService : public CNetAddr
{ {
protected: protected:
unsigned short port; // host order unsigned short port; // host order
public: public:
CIPPort(); CService();
CIPPort(const CIP& ip, unsigned short port); CService(const CNetAddr& ip, unsigned short port);
CIPPort(const struct in_addr& ipv4Addr, unsigned short port); CService(const struct in_addr& ipv4Addr, unsigned short port);
CIPPort(const struct sockaddr_in& addr); CService(const struct sockaddr_in& addr);
CIPPort(const char *pszIp, int port, bool fAllowLookup = false); explicit CService(const char *pszIpPort, int portDefault, bool fAllowLookup = false);
CIPPort(const char *pszIpPort, bool fAllowLookup = false); explicit CService(const char *pszIpPort, bool fAllowLookup = false);
CIPPort(const std::string& strIp, int port, bool fAllowLookup = false); explicit CService(const std::string& strIpPort, int portDefault, bool fAllowLookup = false);
CIPPort(const std::string& strIpPort, bool fAllowLookup = false); explicit CService(const std::string& strIpPort, bool fAllowLookup = false);
void Init(); void Init();
void SetPort(unsigned short portIn); void SetPort(unsigned short portIn);
unsigned short GetPort() const; unsigned short GetPort() const;
bool GetSockAddr(struct sockaddr_in* paddr) const; bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const;
bool ConnectSocket(SOCKET& hSocketRet, int nTimeout = nConnectTimeout) const; bool SetSockAddr(const struct sockaddr* paddr);
friend bool operator==(const CIPPort& a, const CIPPort& b); friend bool operator==(const CService& a, const CService& b);
friend bool operator!=(const CIPPort& a, const CIPPort& b); friend bool operator!=(const CService& a, const CService& b);
friend bool operator<(const CIPPort& a, const CIPPort& b); friend bool operator<(const CService& a, const CService& b);
std::vector<unsigned char> GetKey() const; std::vector<unsigned char> GetKey() const;
std::string ToString() const; std::string ToString() const;
std::string ToStringPort() const;
std::string ToStringIPPort() const;
void print() const; void print() const;
#ifdef USE_IPV6 #ifdef USE_IPV6
CIPPort(const struct in6_addr& ipv6Addr, unsigned short port); CService(const struct in6_addr& ipv6Addr, unsigned short port);
bool GetSockAddr6(struct sockaddr_in6* paddr) const; CService(const struct sockaddr_in6& addr);
CIPPort(const struct sockaddr_in6& addr);
#endif #endif
IMPLEMENT_SERIALIZE IMPLEMENT_SERIALIZE
( (
CIPPort* pthis = const_cast<CIPPort*>(this); CService* pthis = const_cast<CService*>(this);
READWRITE(FLATDATA(ip)); READWRITE(FLATDATA(ip));
unsigned short portN = htons(port); unsigned short portN = htons(port);
READWRITE(portN); READWRITE(portN);
@ -123,13 +133,18 @@ class CIPPort : public CIP
) )
}; };
bool LookupHost(const char *pszName, std::vector<CIP>& vIP, int nMaxSolutions = 0, bool fAllowLookup = true); enum Network ParseNetwork(std::string net);
bool LookupHostNumeric(const char *pszName, std::vector<CIP>& vIP, int nMaxSolutions = 0); bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion = 5);
bool Lookup(const char *pszName, CIPPort& addr, int portDefault = 0, bool fAllowLookup = true); bool GetProxy(enum Network net, CService &addrProxy);
bool LookupNumeric(const char *pszName, CIPPort& addr, int portDefault = 0); bool IsProxy(const CNetAddr &addr);
bool SetNameProxy(CService addrProxy, int nSocksVersion = 5);
// Settings bool GetNameProxy();
extern int fUseProxy; bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true);
extern CIPPort addrProxy; bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0);
bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0);
bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout);
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault = 0, int nTimeout = nConnectTimeout);
#endif #endif

4
protocol.cpp

@ -81,12 +81,12 @@ bool CMessageHeader::IsValid() const
CAddress::CAddress() : CIPPort() CAddress::CAddress() : CService()
{ {
Init(); Init();
} }
CAddress::CAddress(CIPPort ipIn, uint64 nServicesIn) : CIPPort(ipIn) CAddress::CAddress(CService ipIn, uint64 nServicesIn) : CService(ipIn)
{ {
Init(); Init();
nServices = nServicesIn; nServices = nServicesIn;

6
protocol.h

@ -62,18 +62,18 @@ enum
NODE_NETWORK = (1 << 0), NODE_NETWORK = (1 << 0),
}; };
class CAddress : public CIPPort class CAddress : public CService
{ {
public: public:
CAddress(); CAddress();
CAddress(CIPPort ipIn, uint64 nServicesIn=NODE_NETWORK); CAddress(CService ipIn, uint64 nServicesIn=NODE_NETWORK);
void Init(); void Init();
IMPLEMENT_SERIALIZE IMPLEMENT_SERIALIZE
( (
CAddress* pthis = const_cast<CAddress*>(this); CAddress* pthis = const_cast<CAddress*>(this);
CIPPort* pip = (CIPPort*)pthis; CService* pip = (CService*)pthis;
if (fRead) if (fRead)
pthis->Init(); pthis->Init();
if (nType & SER_DISK) if (nType & SER_DISK)

6
test.pl

@ -17,8 +17,8 @@ sub go {
my $sock = IO::Socket::INET->new( my $sock = IO::Socket::INET->new(
Proto => 'udp', Proto => 'udp',
PeerPort => 5353, PeerPort => 53,
PeerAddr => "127.0.0.1", PeerAddr => "vps.sipa.be",
) or die "Could not create socket: $!\n"; ) or die "Could not create socket: $!\n";
while($run) { while($run) {
@ -52,7 +52,7 @@ sub go {
my @threads; my @threads;
for my $i (0..3) { for my $i (0..500) {
$threads[$i] = threads->create(\&go, $i); $threads[$i] = threads->create(\&go, $i);
} }

44
util.h

@ -4,6 +4,7 @@
#include <pthread.h> #include <pthread.h>
#include <errno.h> #include <errno.h>
#include <openssl/sha.h> #include <openssl/sha.h>
#include <stdarg.h>
#include "uint256.h" #include "uint256.h"
@ -26,21 +27,6 @@
#define INVALID_SOCKET (SOCKET)(~0) #define INVALID_SOCKET (SOCKET)(~0)
#define SOCKET_ERROR -1 #define SOCKET_ERROR -1
inline int myclosesocket(SOCKET& hSocket)
{
if (hSocket == INVALID_SOCKET)
return WSAENOTSOCK;
#ifdef WIN32
int ret = closesocket(hSocket);
#else
int ret = close(hSocket);
#endif
hSocket = INVALID_SOCKET;
return ret;
}
#define closesocket(s) myclosesocket(s)
// Wrapper to automatically initialize mutex // Wrapper to automatically initialize mutex
class CCriticalSection class CCriticalSection
{ {
@ -87,10 +73,30 @@ template<typename T1> inline uint256 Hash(const T1 pbegin, const T1 pend)
} }
void static inline Sleep(int nMilliSec) { void static inline Sleep(int nMilliSec) {
struct timespec wa; struct timespec wa;
wa.tv_sec = nMilliSec/1000; wa.tv_sec = nMilliSec/1000;
wa.tv_nsec = (nMilliSec % 1000) * 1000000; wa.tv_nsec = (nMilliSec % 1000) * 1000000;
nanosleep(&wa, NULL); nanosleep(&wa, NULL);
}
std::string vstrprintf(const std::string &format, va_list ap);
std::string static inline strprintf(const std::string &format, ...) {
va_list arg_ptr;
va_start(arg_ptr, format);
std::string ret = vstrprintf(format, arg_ptr);
va_end(arg_ptr);
return ret;
} }
bool static inline error(std::string err) {
return false;
}
std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid = NULL);
std::string DecodeBase32(const std::string& str);
std::string EncodeBase32(const unsigned char* pch, size_t len);
std::string EncodeBase32(const std::string& str);
#endif #endif

Loading…
Cancel
Save