@ -7,6 +7,7 @@
# include <stdio.h>
# include <stdlib.h>
# include <getopt.h>
# include <atomic>
# include "bitcoin.h"
# include "db.h"
@ -34,7 +35,7 @@ public:
CDnsSeedOpts ( ) : nThreads ( 96 ) , nDnsThreads ( 4 ) , nPort ( 53 ) , mbox ( NULL ) , ns ( NULL ) , host ( NULL ) , tor ( NULL ) , fUseTestNet ( false ) , fWipeBan ( false ) , fWipeIgnore ( false ) , ipv4_proxy ( NULL ) , ipv6_proxy ( NULL ) { }
void ParseCommandLine ( int argc , char * * argv ) {
static const char * help = " hush -seeder\n "
static const char * help = " HUSH -seeder\n "
" Usage: %s -h <host> -n <ns> [-m <mbox>] [-t <threads>] [-p <port>] \n "
" \n "
" Options: \n "
@ -188,19 +189,25 @@ extern "C" void* ThreadCrawler(void* data) {
db . ResultMany ( ips ) ;
db . Add ( addr ) ;
} while ( 1 ) ;
return nullptr ;
}
extern " C " int GetIPList ( void * thread , char * requestedHostname , addr_t * addr , int max , int ipv4 , int ipv6 ) ;
class CDnsThread {
public :
dns_opt_t dns_opt ; // must be first
const int id ;
std : : map < uint64_t , vector < addr_t > > cache ;
struct FlagSpecificData {
int nIPv4 , nIPv6 ;
std : : map < uint64_t , time_t > cacheTime ;
std : : vector < addr_t > cache ;
time_t cacheTime ;
unsigned int cacheHits ;
uint64_t dbQueries ;
FlagSpecificData ( ) : nIPv4 ( 0 ) , nIPv6 ( 0 ) , cacheTime ( 0 ) , cacheHits ( 0 ) { }
} ;
dns_opt_t dns_opt ; // must be first
const int id ;
std : : map < uint64_t , FlagSpecificData > perflag ;
std : : atomic < uint64_t > dbQueries ;
std : : set < uint64_t > filterWhitelist ;
void cacheHit ( uint64_t requestedFlags , bool force = false ) {
@ -210,15 +217,16 @@ public:
nets [ NET_IPV6 ] = true ;
}
time_t now = time ( NULL ) ;
cacheHits + + ;
if ( force | | cacheHits > ( cache [ requestedFlags ] . size ( ) * cache [ requestedFlags ] . size ( ) / 400 ) | | ( cacheHits * cacheHits > cache [ requestedFlags ] . size ( ) / 20 & & ( now - cacheTime [ requestedFlags ] > 5 ) ) ) {
FlagSpecificData & thisflag = perflag [ requestedFlags ] ;
thisflag . cacheHits + + ;
if ( force | | thisflag . cacheHits * 400 > ( thisflag . cache . size ( ) * thisflag . cache . size ( ) ) | | ( thisflag . cacheHits * thisflag . cacheHits * 20 > thisflag . cache . size ( ) & & ( now - thisflag . cacheTime > 5 ) ) ) {
set < CNetAddr > ips ;
db . GetIPs ( ips , requestedFlags , 1000 , nets ) ;
dbQueries + + ;
cache [ requestedFlags ] . clear ( ) ;
nIPv4 = 0 ;
nIPv6 = 0 ;
cache [ requestedFlags ] . reserve ( ips . size ( ) ) ;
thisflag . cache . clear ( ) ;
thisflag . nIPv4 = 0 ;
thisflag . nIPv6 = 0 ;
thisflag . cache . reserve ( ips . size ( ) ) ;
for ( set < CNetAddr > : : iterator it = ips . begin ( ) ; it ! = ips . end ( ) ; it + + ) {
struct in_addr addr ;
struct in6_addr addr6 ;
@ -226,18 +234,18 @@ public:
addr_t a ;
a . v = 4 ;
memcpy ( & a . data . v4 , & addr , 4 ) ;
cache [ requestedFlags ] . push_back ( a ) ;
nIPv4 + + ;
thisflag . cache . push_back ( a ) ;
thisflag . nIPv4 + + ;
} else if ( ( * it ) . GetIn6Addr ( & addr6 ) ) {
addr_t a ;
a . v = 6 ;
memcpy ( & a . data . v6 , & addr6 , 16 ) ;
cache [ requestedFlags ] . push_back ( a ) ;
nIPv6 + + ;
thisflag . cache . push_back ( a ) ;
thisflag . nIPv6 + + ;
}
}
cacheHits = 0 ;
cacheTime [ requestedFlags ] = now ;
thisflag . cacheHits = 0 ;
thisflag . cacheTime = now ;
}
}
@ -250,12 +258,8 @@ public:
dns_opt . cb = GetIPList ;
dns_opt . port = opts - > nPort ;
dns_opt . nRequests = 0 ;
cache . clear ( ) ;
cacheTime . clear ( ) ;
cacheHits = 0 ;
dbQueries = 0 ;
nIPv4 = 0 ;
nIPv6 = 0 ;
perflag . clear ( ) ;
filterWhitelist = opts - > filter_whitelist ;
}
@ -280,8 +284,9 @@ extern "C" int GetIPList(void *data, char *requestedHostname, addr_t* addr, int
else if ( strcasecmp ( requestedHostname , thread - > dns_opt . host ) )
return 0 ;
thread - > cacheHit ( requestedFlags ) ;
unsigned int size = thread - > cache [ requestedFlags ] . size ( ) ;
unsigned int maxmax = ( ipv4 ? thread - > nIPv4 : 0 ) + ( ipv6 ? thread - > nIPv6 : 0 ) ;
auto & thisflag = thread - > perflag [ requestedFlags ] ;
unsigned int size = thisflag . cache . size ( ) ;
unsigned int maxmax = ( ipv4 ? thisflag . nIPv4 : 0 ) + ( ipv6 ? thisflag . nIPv6 : 0 ) ;
if ( max > size )
max = size ;
if ( max > maxmax )
@ -290,16 +295,16 @@ extern "C" int GetIPList(void *data, char *requestedHostname, addr_t* addr, int
while ( i < max ) {
int j = i + ( rand ( ) % ( size - i ) ) ;
do {
bool ok = ( ipv4 & & thread - > cache [ requestedFlags ] [ j ] . v = = 4 ) | |
( ipv6 & & thread - > cache [ requestedFlags ] [ j ] . v = = 6 ) ;
bool ok = ( ipv4 & & thisflag . cache [ j ] . v = = 4 ) | |
( ipv6 & & thisflag . cache [ j ] . v = = 6 ) ;
if ( ok ) break ;
j + + ;
if ( j = = size )
j = i ;
} while ( 1 ) ;
addr [ i ] = thread - > cache [ requestedFlags ] [ j ] ;
thread - > cache [ requestedFlags ] [ j ] = thread - > cache [ requestedFlags ] [ i ] ;
thread - > cache [ requestedFlags ] [ i ] = addr [ i ] ;
addr [ i ] = thisflag . cache [ j ] ;
thisflag . cache [ j ] = thisflag . cache [ i ] ;
thisflag . cache [ i ] = addr [ i ] ;
i + + ;
}
return max ;
@ -310,6 +315,7 @@ vector<CDnsThread*> dnsThread;
extern " C " void * ThreadDNS ( void * arg ) {
CDnsThread * thread = ( CDnsThread * ) arg ;
thread - > run ( ) ;
return nullptr ;
}
int StatCompare ( const CAddrReport & a , const CAddrReport & b ) {
@ -359,6 +365,7 @@ extern "C" void* ThreadDumper(void*) {
fclose ( ff ) ;
}
} while ( 1 ) ;
return nullptr ;
}
extern " C " void * ThreadStats ( void * ) {
@ -387,15 +394,14 @@ extern "C" void* ThreadStats(void*) {
printf ( " %s %i/%i available (%i tried in %is, %i new, %i active), %i banned; %llu DNS requests, %llu db queries " , c , stats . nGood , stats . nAvail , stats . nTracked , stats . nAge , stats . nNew , stats . nAvail - stats . nTracked - stats . nNew , stats . nBanned , ( unsigned long long ) requests , ( unsigned long long ) queries ) ;
Sleep ( 1000 ) ;
} while ( 1 ) ;
return nullptr ;
}
static const string mainnet_seeds [ ] = { " explorer.myhush.org " , " " } ;
static const string testnet_seeds [ ] = { " stilgar.myhush.org " , " " } ;
static const string * seeds = mainnet_seeds ;
extern " C " void * ThreadSeeder ( void * ) {
//if (!fTestNet){
// db.Add(CService("kjy2eqzk4zwi5zd3.onion", 8333 ), true);
// db.Add(CService("kjy2eqzk4zwi5zd3.onion", 8888 ), true);
//}
do {
for ( int i = 0 ; seeds [ i ] ! = " " ; i + + ) {
@ -407,6 +413,7 @@ extern "C" void* ThreadSeeder(void*) {
}
Sleep ( 1800000 ) ;
} while ( 1 ) ;
return nullptr ;
}
int main ( int argc , char * * argv ) {
@ -446,10 +453,7 @@ int main(int argc, char **argv) {
bool fDNS = true ;
if ( opts . fUseTestNet ) {
printf ( " Using testnet. \n " ) ;
pchMessageStart [ 0 ] = 0xFA ;
pchMessageStart [ 1 ] = 0x1A ;
pchMessageStart [ 2 ] = 0x24 ;
pchMessageStart [ 3 ] = 0xB6 ;
std : : copy ( std : : begin ( pchMessageStart_testnet ) , std : : end ( pchMessageStart_testnet ) , std : : begin ( pchMessageStart ) ) ;
seeds = testnet_seeds ;
fTestNet = true ;
}