Browse Source

IPv6/AAAA record support

pull/1/head
Pieter Wuille 13 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 @@ @@ -1,8 +1,8 @@
dnsseed: dns.o bitcoin.o netbase.o protocol.o db.o main.o
g++ -pthread -lcrypto -o 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 -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
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
gcc -pthread -std=c99 -O2 -ggdb3 -march=nocona dns.c -c -o dns.o

12
bitcoin.cpp

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

2
bitcoin.h

@ -3,6 +3,6 @@ @@ -3,6 +3,6 @@
#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

18
db.cpp

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

35
db.h

@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
#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();
while (str.size() < 22) str += ' ';
return str;
@ -44,7 +44,7 @@ public: @@ -44,7 +44,7 @@ public:
class CAddrReport {
public:
CIPPort ip;
CService ip;
int clientVersion;
double uptime[5];
std::string clientSubVersion;
@ -53,7 +53,7 @@ public: @@ -53,7 +53,7 @@ public:
class CAddrInfo {
private:
CIPPort ip;
CService ip;
uint64_t services;
int64 lastTry;
int64 ourLastTry;
@ -87,7 +87,6 @@ public: @@ -87,7 +87,6 @@ public:
if (ip.GetPort() != 8333) return false;
if (!(services & NODE_NETWORK)) return false;
if (!ip.IsRoutable()) return false;
if (!ip.IsIPv4()) return false;
if (clientVersion && clientVersion < 32400) return false;
if (total <= 3 && success * 2 >= total) return true;
@ -170,7 +169,7 @@ private: @@ -170,7 +169,7 @@ private:
mutable CCriticalSection cs;
int nId; // number of address id's
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::set<int> unkId; // set of nodes not yet tried (b)
std::set<int> goodId; // set of good nodes (d, good e)
@ -179,15 +178,15 @@ private: @@ -179,15 +178,15 @@ private:
protected:
// internal routines that assume proper locks are acquired
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)
void Good_(const CIPPort &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 Skipped_(const CIPPort &ip); // mark an IP as skipped (must have been returned by Get_)
int Lookup_(const CIPPort &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)
bool Get_(CService &ip, int& wait); // get an IP to test (must call Good_, Bad_, or Skipped_ on result afterwards)
void Good_(const CService &ip, int clientV, std::string clientSV); // mark an IP as good (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 CService &ip); // mark an IP as skipped (must have been returned by Get_)
int Lookup_(const CService &ip); // look up id of an IP
void GetIPs_(std::set<CNetAddr>& ips, int max, const bool* nets); // get a random set of IPs (shared lock only)
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) {
SHARED_CRITICAL_BLOCK(cs) {
@ -272,24 +271,24 @@ public: @@ -272,24 +271,24 @@ public:
for (int i=0; i<vAddr.size(); i++)
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)
Good_(addr, clientVersion, clientSubVersion);
}
void Skipped(const CIPPort &addr) {
void Skipped(const CService &addr) {
CRITICAL_BLOCK(cs)
Skipped_(addr);
}
void Bad(const CIPPort &addr, int ban = 0) {
void Bad(const CService &addr, int ban = 0) {
CRITICAL_BLOCK(cs)
Bad_(addr, ban);
}
bool Get(CIPPort &ip, int& wait) {
bool Get(CService &ip, int& wait) {
CRITICAL_BLOCK(cs)
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)
GetIPs_(ips, max, fOnlyIPv4);
GetIPs_(ips, max, nets);
}
};

28
dns.c

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

10
dns.h

@ -3,6 +3,14 @@ @@ -3,6 +3,14 @@
#include <stdint.h>
typedef struct {
int v;
union {
unsigned char v4[4];
unsigned char v6[16];
} data;
} addr_t;
typedef struct {
int port;
int datattl;
@ -10,7 +18,7 @@ typedef struct { @@ -10,7 +18,7 @@ typedef struct {
const char *host;
const char *ns;
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
uint64_t nRequests;
} dns_opt_t;

62
main.cpp

@ -105,7 +105,7 @@ CAddrDb db; @@ -105,7 +105,7 @@ CAddrDb db;
extern "C" void* ThreadCrawler(void* data) {
do {
CIPPort ip;
CService ip;
int wait = 5;
if (!db.Get(ip, wait)) {
wait *= 1000;
@ -127,29 +127,50 @@ extern "C" void* ThreadCrawler(void* data) { @@ -127,29 +127,50 @@ extern "C" void* ThreadCrawler(void* data) {
} 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 {
public:
dns_opt_t dns_opt;
vector<struct in_addr> cache;
vector<addr_t> cache;
int nIPv4, nIPv6;
time_t cacheTime;
unsigned int cacheHits;
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);
cacheHits++;
if (force || cacheHits > (cache.size()*cache.size()/400) || (cacheHits*cacheHits > cache.size() / 20 && (now - cacheTime > 5))) {
set<CIP> ips;
db.GetIPs(ips, 1000, ipv4only);
set<CNetAddr> ips;
db.GetIPs(ips, 1000, nets);
dbQueries++;
cache.clear();
nIPv4 = 0;
nIPv6 = 0;
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 in6_addr addr6;
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;
@ -171,7 +192,9 @@ public: @@ -171,7 +192,9 @@ public:
cacheTime = 0;
cacheHits = 0;
dbQueries = 0;
cacheHit(true, true);
nIPv4 = 0;
nIPv6 = 0;
cacheHit(true);
}
void run() {
@ -179,14 +202,21 @@ public: @@ -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;
thread->cacheHit(ipv4only);
unsigned int size = thread->cache.size();
thread->cacheHit();
unsigned int size = (ipv4 ? thread->nIPv4 : 0) + (ipv6 ? thread->nIPv6 : 0);
if (max > size)
max = size;
for (int i=0; i<max; i++) {
int i=0;
while (i<max) {
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];
thread->cache[j] = thread->cache[i];
thread->cache[i] = addr[i];
@ -269,10 +299,10 @@ static const string seeds[] = {"dnsseed.bluematt.me", "bitseed.xf2.org", "dnssee @@ -269,10 +299,10 @@ static const string seeds[] = {"dnsseed.bluematt.me", "bitseed.xf2.org", "dnssee
extern "C" void* ThreadSeeder(void*) {
do {
for (int i=0; i<sizeof(seeds)/sizeof(seeds[0]); i++) {
vector<CIP> ips;
vector<CNetAddr> ips;
LookupHost(seeds[i].c_str(), ips);
for (vector<CIP>::iterator it = ips.begin(); it != ips.end(); it++) {
db.Add(CIPPort(*it, 8333), true);
for (vector<CNetAddr>::iterator it = ips.begin(); it != ips.end(); it++) {
db.Add(CService(*it, 8333), true);
}
}
Sleep(1800000);

827
netbase.cpp

File diff suppressed because it is too large Load Diff

123
netbase.h

@ -1,49 +1,52 @@ @@ -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
// 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
#define BITCOIN_NETBASE_H
#include <string>
#include <vector>
#include "serialize.h"
#include "compat.h"
extern int nConnectTimeout;
#ifdef WIN32
#include <winsock2.h>
#include <mswsock.h>
#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>
// In MSVC, this is defined as a macro, undefine it to prevent a compile and link error
#undef SetPort
#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 bool fNameLookup;
// IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
class CIP
/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */
class CNetAddr
{
protected:
unsigned char ip[16]; // in network byte order
public:
CIP();
CIP(const struct in_addr& ipv4Addr);
CIP(const char *pszIp, bool fAllowLookup = false);
CIP(const std::string &strIp, bool fAllowLookup = false);
CNetAddr();
CNetAddr(const struct in_addr& ipv4Addr);
explicit CNetAddr(const char *pszIp, bool fAllowLookup = false);
explicit CNetAddr(const std::string &strIp, bool fAllowLookup = false);
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 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 IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
@ -54,25 +57,30 @@ class CIP @@ -54,25 +57,30 @@ class CIP
bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64)
bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96)
bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96)
bool IsTor() const;
bool IsI2P() const;
bool IsLocal() const;
bool IsRoutable() const;
bool IsValid() const;
bool IsMulticast() const;
enum Network GetNetwork() const;
std::string ToString() const;
std::string ToStringIP() const;
int GetByte(int n) const;
int64 GetHash() const;
bool GetInAddr(struct in_addr* pipv4Addr) const;
std::vector<unsigned char> GetGroup() const;
int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const;
void print() const;
#ifdef USE_IPV6
CIP(const struct in6_addr& pipv6Addr);
CNetAddr(const struct in6_addr& pipv6Addr);
bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
#endif
friend bool operator==(const CIP& a, const CIP& b);
friend bool operator!=(const CIP& a, const CIP& b);
friend bool operator<(const CIP& a, const CIP& b);
friend bool operator==(const CNetAddr& a, const CNetAddr& b);
friend bool operator!=(const CNetAddr& a, const CNetAddr& b);
friend bool operator<(const CNetAddr& a, const CNetAddr& b);
IMPLEMENT_SERIALIZE
(
@ -80,41 +88,43 @@ class CIP @@ -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:
unsigned short port; // host order
public:
CIPPort();
CIPPort(const CIP& ip, unsigned short port);
CIPPort(const struct in_addr& ipv4Addr, unsigned short port);
CIPPort(const struct sockaddr_in& addr);
CIPPort(const char *pszIp, int port, bool fAllowLookup = false);
CIPPort(const char *pszIpPort, bool fAllowLookup = false);
CIPPort(const std::string& strIp, int port, bool fAllowLookup = false);
CIPPort(const std::string& strIpPort, bool fAllowLookup = false);
CService();
CService(const CNetAddr& ip, unsigned short port);
CService(const struct in_addr& ipv4Addr, unsigned short port);
CService(const struct sockaddr_in& addr);
explicit CService(const char *pszIpPort, int portDefault, bool fAllowLookup = false);
explicit CService(const char *pszIpPort, bool fAllowLookup = false);
explicit CService(const std::string& strIpPort, int portDefault, bool fAllowLookup = false);
explicit CService(const std::string& strIpPort, bool fAllowLookup = false);
void Init();
void SetPort(unsigned short portIn);
unsigned short GetPort() const;
bool GetSockAddr(struct sockaddr_in* paddr) const;
bool ConnectSocket(SOCKET& hSocketRet, int nTimeout = nConnectTimeout) const;
friend bool operator==(const CIPPort& a, const CIPPort& b);
friend bool operator!=(const CIPPort& a, const CIPPort& b);
friend bool operator<(const CIPPort& a, const CIPPort& b);
bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const;
bool SetSockAddr(const struct sockaddr* paddr);
friend bool operator==(const CService& a, const CService& b);
friend bool operator!=(const CService& a, const CService& b);
friend bool operator<(const CService& a, const CService& b);
std::vector<unsigned char> GetKey() const;
std::string ToString() const;
std::string ToStringPort() const;
std::string ToStringIPPort() const;
void print() const;
#ifdef USE_IPV6
CIPPort(const struct in6_addr& ipv6Addr, unsigned short port);
bool GetSockAddr6(struct sockaddr_in6* paddr) const;
CIPPort(const struct sockaddr_in6& addr);
CService(const struct in6_addr& ipv6Addr, unsigned short port);
CService(const struct sockaddr_in6& addr);
#endif
IMPLEMENT_SERIALIZE
(
CIPPort* pthis = const_cast<CIPPort*>(this);
CService* pthis = const_cast<CService*>(this);
READWRITE(FLATDATA(ip));
unsigned short portN = htons(port);
READWRITE(portN);
@ -123,13 +133,18 @@ class CIPPort : public CIP @@ -123,13 +133,18 @@ class CIPPort : public CIP
)
};
bool LookupHost(const char *pszName, std::vector<CIP>& vIP, int nMaxSolutions = 0, bool fAllowLookup = true);
bool LookupHostNumeric(const char *pszName, std::vector<CIP>& vIP, int nMaxSolutions = 0);
bool Lookup(const char *pszName, CIPPort& addr, int portDefault = 0, bool fAllowLookup = true);
bool LookupNumeric(const char *pszName, CIPPort& addr, int portDefault = 0);
// Settings
extern int fUseProxy;
extern CIPPort addrProxy;
enum Network ParseNetwork(std::string net);
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion = 5);
bool GetProxy(enum Network net, CService &addrProxy);
bool IsProxy(const CNetAddr &addr);
bool SetNameProxy(CService addrProxy, int nSocksVersion = 5);
bool GetNameProxy();
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true);
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

4
protocol.cpp

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

6
protocol.h

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

6
test.pl

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

44
util.h

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
#include <pthread.h>
#include <errno.h>
#include <openssl/sha.h>
#include <stdarg.h>
#include "uint256.h"
@ -26,21 +27,6 @@ @@ -26,21 +27,6 @@
#define INVALID_SOCKET (SOCKET)(~0)
#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
class CCriticalSection
{
@ -87,10 +73,30 @@ template<typename T1> inline uint256 Hash(const T1 pbegin, const T1 pend) @@ -87,10 +73,30 @@ template<typename T1> inline uint256 Hash(const T1 pbegin, const T1 pend)
}
void static inline Sleep(int nMilliSec) {
struct timespec wa;
wa.tv_sec = nMilliSec/1000;
wa.tv_nsec = (nMilliSec % 1000) * 1000000;
nanosleep(&wa, NULL);
struct timespec wa;
wa.tv_sec = nMilliSec/1000;
wa.tv_nsec = (nMilliSec % 1000) * 1000000;
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

Loading…
Cancel
Save