2012-02-23 18:01:09 +01:00
# include <algorithm>
2013-04-15 05:16:20 +02:00
# define __STDC_FORMAT_MACROS
# include <inttypes.h>
2011-12-20 05:20:50 +01:00
# include <pthread.h>
2012-06-21 04:09:05 +02:00
# include <signal.h>
2012-01-01 19:18:56 +01:00
# include <stdio.h>
# include <stdlib.h>
# include <getopt.h>
2016-10-29 21:08:46 +02:00
# include <atomic>
2011-12-20 05:20:50 +01:00
# include "bitcoin.h"
# include "db.h"
using namespace std ;
2013-01-24 05:28:07 +01:00
bool fTestNet = false ;
2012-01-01 19:18:56 +01:00
class CDnsSeedOpts {
public :
int nThreads ;
int nPort ;
2012-05-04 01:15:49 +02:00
int nDnsThreads ;
2013-01-24 05:28:07 +01:00
int fUseTestNet ;
2012-05-30 19:13:00 +02:00
int fWipeBan ;
int fWipeIgnore ;
2012-01-01 19:18:56 +01:00
const char * mbox ;
const char * ns ;
const char * host ;
2012-05-30 19:13:00 +02:00
const char * tor ;
2020-08-06 03:23:55 +02:00
const char * ip_addr ;
2015-07-20 13:48:19 +02:00
const char * ipv4_proxy ;
2015-07-26 17:32:05 +02:00
const char * ipv6_proxy ;
2016-06-07 18:54:04 +02:00
std : : set < uint64_t > filter_whitelist ;
2013-04-13 21:45:52 +02:00
2020-08-06 03:23:55 +02:00
CDnsSeedOpts ( ) : nThreads ( 96 ) , nDnsThreads ( 4 ) , ip_addr ( " :: " ) , nPort ( 53 ) , mbox ( NULL ) , ns ( NULL ) , host ( NULL ) , tor ( NULL ) , fUseTestNet ( false ) , fWipeBan ( false ) , fWipeIgnore ( false ) , ipv4_proxy ( NULL ) , ipv6_proxy ( NULL ) { }
2013-04-13 21:45:52 +02:00
2012-01-01 19:18:56 +01:00
void ParseCommandLine ( int argc , char * * argv ) {
2021-04-12 15:35:35 +02:00
static const char * help = " LBRY-seeder \n "
2012-01-01 23:23:21 +01:00
" Usage: %s -h <host> -n <ns> [-m <mbox>] [-t <threads>] [-p <port>] \n "
" \n "
" Options: \n "
" -h <host> Hostname of the DNS seed \n "
" -n <ns> Hostname of the nameserver \n "
" -m <mbox> E-Mail address reported in SOA records \n "
2013-08-09 09:56:17 +02:00
" -t <threads> Number of crawlers to run in parallel (default 96) \n "
" -d <threads> Number of DNS server threads (default 4) \n "
2020-08-06 03:23:55 +02:00
" -a <address> Address to listen on (default ::) \n "
2012-01-01 23:23:21 +01:00
" -p <port> UDP port to listen on (default 53) \n "
2012-05-30 19:13:00 +02:00
" -o <ip:port> Tor proxy IP/Port \n "
2015-07-27 11:49:51 +02:00
" -i <ip:port> IPV4 SOCKS5 proxy IP/Port \n "
" -k <ip:port> IPV6 SOCKS5 proxy IP/Port \n "
2016-06-07 18:54:04 +02:00
" -w f1,f2,... Allow these flag combinations as filters \n "
2013-01-24 05:28:07 +01:00
" --testnet Use testnet \n "
2012-05-30 19:13:00 +02:00
" --wipeban Wipe list of banned nodes \n "
" --wipeignore Wipe list of ignored nodes \n "
2012-01-01 23:23:21 +01:00
" -?, --help Show this text \n "
" \n " ;
bool showHelp = false ;
2012-01-01 19:18:56 +01:00
while ( 1 ) {
static struct option long_options [ ] = {
{ " host " , required_argument , 0 , ' h ' } ,
{ " ns " , required_argument , 0 , ' n ' } ,
{ " mbox " , required_argument , 0 , ' m ' } ,
{ " threads " , required_argument , 0 , ' t ' } ,
2012-05-04 01:15:49 +02:00
{ " dnsthreads " , required_argument , 0 , ' d ' } ,
2020-08-06 03:23:55 +02:00
{ " address " , required_argument , 0 , ' a ' } ,
2012-01-01 19:18:56 +01:00
{ " port " , required_argument , 0 , ' p ' } ,
2012-05-30 19:13:00 +02:00
{ " onion " , required_argument , 0 , ' o ' } ,
2015-07-26 17:32:05 +02:00
{ " proxyipv4 " , required_argument , 0 , ' i ' } ,
2015-07-27 11:49:51 +02:00
{ " proxyipv6 " , required_argument , 0 , ' k ' } ,
2016-06-07 18:54:04 +02:00
{ " filter " , required_argument , 0 , ' w ' } ,
2013-01-24 05:28:07 +01:00
{ " testnet " , no_argument , & fUseTestNet , 1 } ,
2012-05-30 19:13:00 +02:00
{ " wipeban " , no_argument , & fWipeBan , 1 } ,
{ " wipeignore " , no_argument , & fWipeBan , 1 } ,
2012-01-01 23:23:21 +01:00
{ " help " , no_argument , 0 , ' h ' } ,
2012-01-01 19:18:56 +01:00
{ 0 , 0 , 0 , 0 }
} ;
int option_index = 0 ;
2021-04-12 15:35:35 +02:00
int c = getopt_long ( argc , argv , " h:n:m:t:a:p:d:o:i:k:w:? " , long_options , & option_index ) ;
2012-01-01 19:18:56 +01:00
if ( c = = - 1 ) break ;
switch ( c ) {
case ' h ' : {
host = optarg ;
break ;
}
2021-04-12 15:35:35 +02:00
2012-01-01 19:18:56 +01:00
case ' m ' : {
mbox = optarg ;
break ;
}
2021-04-12 15:35:35 +02:00
2012-01-01 19:18:56 +01:00
case ' n ' : {
ns = optarg ;
break ;
}
2021-04-12 15:35:35 +02:00
2012-01-01 19:18:56 +01:00
case ' t ' : {
int n = strtol ( optarg , NULL , 10 ) ;
if ( n > 0 & & n < 1000 ) nThreads = n ;
2012-01-01 23:23:21 +01:00
break ;
2012-01-01 19:18:56 +01:00
}
2012-05-04 01:15:49 +02:00
case ' d ' : {
int n = strtol ( optarg , NULL , 10 ) ;
if ( n > 0 & & n < 1000 ) nDnsThreads = n ;
break ;
}
2020-08-06 03:23:55 +02:00
case ' a ' : {
if ( strchr ( optarg , ' : ' ) = = NULL ) {
char * ip4_addr = ( char * ) malloc ( strlen ( optarg ) + 8 ) ;
strcpy ( ip4_addr , " ::FFFF: " ) ;
strcat ( ip4_addr , optarg ) ;
ip_addr = ip4_addr ;
} else {
ip_addr = optarg ;
}
break ;
}
2012-01-01 19:18:56 +01:00
case ' p ' : {
int p = strtol ( optarg , NULL , 10 ) ;
if ( p > 0 & & p < 65536 ) nPort = p ;
2012-01-01 23:23:21 +01:00
break ;
}
2015-07-26 17:32:05 +02:00
2012-05-30 19:13:00 +02:00
case ' o ' : {
tor = optarg ;
break ;
}
2015-07-20 13:48:19 +02:00
case ' i ' : {
ipv4_proxy = optarg ;
break ;
}
2012-05-30 19:13:00 +02:00
2015-07-26 17:32:05 +02:00
case ' k ' : {
ipv6_proxy = optarg ;
break ;
}
2016-06-07 18:54:04 +02:00
case ' w ' : {
char * ptr = optarg ;
while ( * ptr ! = 0 ) {
unsigned long l = strtoul ( ptr , & ptr , 0 ) ;
if ( * ptr = = ' , ' ) {
ptr + + ;
} else if ( * ptr ! = 0 ) {
break ;
}
filter_whitelist . insert ( l ) ;
}
break ;
}
2012-01-01 23:23:21 +01:00
case ' ? ' : {
showHelp = true ;
break ;
2012-01-01 19:18:56 +01:00
}
}
}
2016-06-07 18:54:04 +02:00
if ( filter_whitelist . empty ( ) ) {
2019-08-22 17:34:58 +02:00
filter_whitelist . insert ( NODE_NETWORK ) ; // x1
filter_whitelist . insert ( NODE_NETWORK | NODE_BLOOM ) ; // x5
filter_whitelist . insert ( NODE_NETWORK | NODE_WITNESS ) ; // x9
filter_whitelist . insert ( NODE_NETWORK | NODE_WITNESS | NODE_COMPACT_FILTERS ) ; // x49
filter_whitelist . insert ( NODE_NETWORK | NODE_WITNESS | NODE_BLOOM ) ; // xd
filter_whitelist . insert ( NODE_NETWORK_LIMITED ) ; // x400
filter_whitelist . insert ( NODE_NETWORK_LIMITED | NODE_BLOOM ) ; // x404
filter_whitelist . insert ( NODE_NETWORK_LIMITED | NODE_WITNESS ) ; // x408
filter_whitelist . insert ( NODE_NETWORK_LIMITED | NODE_WITNESS | NODE_COMPACT_FILTERS ) ; // x448
filter_whitelist . insert ( NODE_NETWORK_LIMITED | NODE_WITNESS | NODE_BLOOM ) ; // x40c
2016-06-07 18:54:04 +02:00
}
2012-02-27 03:31:34 +01:00
if ( host ! = NULL & & ns = = NULL ) showHelp = true ;
2012-01-01 23:23:21 +01:00
if ( showHelp ) fprintf ( stderr , help , argv [ 0 ] ) ;
2012-01-01 19:18:56 +01:00
}
} ;
2011-12-20 14:29:21 +01:00
# include "dns.h"
2011-12-20 05:20:50 +01:00
CAddrDb db ;
extern " C " void * ThreadCrawler ( void * data ) {
2013-08-09 10:28:52 +02:00
int * nThreads = ( int * ) data ;
2011-12-20 05:20:50 +01:00
do {
2013-04-13 22:37:06 +02:00
std : : vector < CServiceResult > ips ;
2011-12-20 06:42:48 +01:00
int wait = 5 ;
2013-04-13 22:46:23 +02:00
db . GetMany ( ips , 16 , wait ) ;
2013-04-25 01:55:26 +02:00
int64 now = time ( NULL ) ;
2013-04-13 22:37:06 +02:00
if ( ips . empty ( ) ) {
2011-12-20 09:31:28 +01:00
wait * = 1000 ;
2013-08-09 10:28:52 +02:00
wait + = rand ( ) % ( 500 * * nThreads ) ;
2011-12-20 09:31:28 +01:00
Sleep ( wait ) ;
2011-12-20 05:20:50 +01:00
continue ;
}
vector < CAddress > addr ;
2013-04-13 22:37:06 +02:00
for ( int i = 0 ; i < ips . size ( ) ; i + + ) {
CServiceResult & res = ips [ i ] ;
res . nBanTime = 0 ;
res . nClientV = 0 ;
res . nHeight = 0 ;
res . strClientV = " " ;
2020-10-10 04:37:28 +02:00
res . services = 0 ;
2016-05-31 22:07:07 +02:00
bool getaddr = res . ourLastSuccess + 86400 < now ;
2020-10-10 04:37:28 +02:00
res . fGood = TestNode ( res . service , res . nBanTime , res . nClientV , res . strClientV , res . nHeight , getaddr ? & addr : NULL , res . services ) ;
2011-12-20 05:20:50 +01:00
}
2013-04-13 22:37:06 +02:00
db . ResultMany ( ips ) ;
db . Add ( addr ) ;
2011-12-20 05:20:50 +01:00
} while ( 1 ) ;
2016-10-29 21:08:46 +02:00
return nullptr ;
2011-12-20 05:20:50 +01:00
}
2016-05-21 12:19:25 +02:00
extern " C " int GetIPList ( void * thread , char * requestedHostname , addr_t * addr , int max , int ipv4 , int ipv6 ) ;
2012-05-04 00:08:26 +02:00
2012-05-04 01:15:49 +02:00
class CDnsThread {
public :
2016-10-29 21:08:46 +02:00
struct FlagSpecificData {
int nIPv4 , nIPv6 ;
std : : vector < addr_t > cache ;
time_t cacheTime ;
unsigned int cacheHits ;
FlagSpecificData ( ) : nIPv4 ( 0 ) , nIPv6 ( 0 ) , cacheTime ( 0 ) , cacheHits ( 0 ) { }
} ;
2012-05-26 00:09:07 +02:00
dns_opt_t dns_opt ; // must be first
const int id ;
2016-10-29 21:08:46 +02:00
std : : map < uint64_t , FlagSpecificData > perflag ;
std : : atomic < uint64_t > dbQueries ;
2016-06-07 18:54:04 +02:00
std : : set < uint64_t > filterWhitelist ;
2012-05-04 01:15:49 +02:00
2016-05-21 12:19:25 +02:00
void cacheHit ( uint64_t requestedFlags , bool force = false ) {
2012-05-25 15:41:27 +02:00
static bool nets [ NET_MAX ] = { } ;
if ( ! nets [ NET_IPV4 ] ) {
nets [ NET_IPV4 ] = true ;
nets [ NET_IPV6 ] = true ;
}
2012-05-04 01:15:49 +02:00
time_t now = time ( NULL ) ;
2017-01-12 23:59:33 +01:00
FlagSpecificData & thisflag = perflag [ requestedFlags ] ;
2016-10-29 21:08:46 +02:00
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 ) ) ) {
2012-05-25 15:41:27 +02:00
set < CNetAddr > ips ;
2016-05-21 12:19:25 +02:00
db . GetIPs ( ips , requestedFlags , 1000 , nets ) ;
2012-05-04 01:15:49 +02:00
dbQueries + + ;
2016-10-29 21:08:46 +02:00
thisflag . cache . clear ( ) ;
thisflag . nIPv4 = 0 ;
thisflag . nIPv6 = 0 ;
thisflag . cache . reserve ( ips . size ( ) ) ;
2012-05-25 15:41:27 +02:00
for ( set < CNetAddr > : : iterator it = ips . begin ( ) ; it ! = ips . end ( ) ; it + + ) {
2012-05-04 01:15:49 +02:00
struct in_addr addr ;
2012-05-25 15:41:27 +02:00
struct in6_addr addr6 ;
2012-05-04 01:15:49 +02:00
if ( ( * it ) . GetInAddr ( & addr ) ) {
2012-05-25 15:41:27 +02:00
addr_t a ;
a . v = 4 ;
memcpy ( & a . data . v4 , & addr , 4 ) ;
2016-10-29 21:08:46 +02:00
thisflag . cache . push_back ( a ) ;
thisflag . nIPv4 + + ;
2012-05-25 15:41:27 +02:00
} else if ( ( * it ) . GetIn6Addr ( & addr6 ) ) {
addr_t a ;
a . v = 6 ;
memcpy ( & a . data . v6 , & addr6 , 16 ) ;
2016-10-29 21:08:46 +02:00
thisflag . cache . push_back ( a ) ;
thisflag . nIPv6 + + ;
2012-05-04 01:15:49 +02:00
}
2012-05-04 00:08:26 +02:00
}
2016-10-29 21:08:46 +02:00
thisflag . cacheHits = 0 ;
thisflag . cacheTime = now ;
2011-12-20 22:18:13 +01:00
}
2012-05-04 01:15:49 +02:00
}
2012-05-26 00:09:07 +02:00
CDnsThread ( CDnsSeedOpts * opts , int idIn ) : id ( idIn ) {
2012-05-04 01:15:49 +02:00
dns_opt . host = opts - > host ;
dns_opt . ns = opts - > ns ;
dns_opt . mbox = opts - > mbox ;
2015-07-29 15:19:21 +02:00
dns_opt . datattl = 3600 ;
2012-05-04 01:15:49 +02:00
dns_opt . nsttl = 40000 ;
dns_opt . cb = GetIPList ;
2020-08-06 03:23:55 +02:00
dns_opt . addr = opts - > ip_addr ;
2012-05-04 01:15:49 +02:00
dns_opt . port = opts - > nPort ;
dns_opt . nRequests = 0 ;
dbQueries = 0 ;
2016-10-29 21:08:46 +02:00
perflag . clear ( ) ;
2016-06-07 18:54:04 +02:00
filterWhitelist = opts - > filter_whitelist ;
2012-05-04 00:08:26 +02:00
}
2012-05-04 01:15:49 +02:00
void run ( ) {
dnsserver ( & dns_opt ) ;
}
} ;
2016-05-21 12:19:25 +02:00
extern " C " int GetIPList ( void * data , char * requestedHostname , addr_t * addr , int max , int ipv4 , int ipv6 ) {
2012-05-04 01:15:49 +02:00
CDnsThread * thread = ( CDnsThread * ) data ;
2016-05-21 12:19:25 +02:00
uint64_t requestedFlags = 0 ;
int hostlen = strlen ( requestedHostname ) ;
if ( hostlen > 1 & & requestedHostname [ 0 ] = = ' x ' & & requestedHostname [ 1 ] ! = ' 0 ' ) {
char * pEnd ;
uint64_t flags = ( uint64_t ) strtoull ( requestedHostname + 1 , & pEnd , 16 ) ;
2016-06-02 22:10:44 +02:00
if ( * pEnd = = ' . ' & & pEnd < = requestedHostname + 17 & & std : : find ( thread - > filterWhitelist . begin ( ) , thread - > filterWhitelist . end ( ) , flags ) ! = thread - > filterWhitelist . end ( ) )
2016-05-21 12:19:25 +02:00
requestedFlags = flags ;
2016-06-02 22:10:44 +02:00
else
return 0 ;
2016-05-21 12:19:25 +02:00
}
2016-06-02 22:10:44 +02:00
else if ( strcasecmp ( requestedHostname , thread - > dns_opt . host ) )
return 0 ;
2016-05-21 12:19:25 +02:00
thread - > cacheHit ( requestedFlags ) ;
2016-10-29 21:08:46 +02:00
auto & thisflag = thread - > perflag [ requestedFlags ] ;
unsigned int size = thisflag . cache . size ( ) ;
unsigned int maxmax = ( ipv4 ? thisflag . nIPv4 : 0 ) + ( ipv6 ? thisflag . nIPv6 : 0 ) ;
2012-05-04 01:15:49 +02:00
if ( max > size )
max = size ;
2012-05-26 00:09:07 +02:00
if ( max > maxmax )
max = maxmax ;
2012-05-25 15:41:27 +02:00
int i = 0 ;
while ( i < max ) {
2012-05-04 01:15:49 +02:00
int j = i + ( rand ( ) % ( size - i ) ) ;
2012-05-25 15:41:27 +02:00
do {
2016-10-29 21:08:46 +02:00
bool ok = ( ipv4 & & thisflag . cache [ j ] . v = = 4 ) | |
( ipv6 & & thisflag . cache [ j ] . v = = 6 ) ;
2012-05-25 15:41:27 +02:00
if ( ok ) break ;
2012-05-26 00:09:07 +02:00
j + + ;
if ( j = = size )
j = i ;
2012-05-25 15:41:27 +02:00
} while ( 1 ) ;
2016-10-29 21:08:46 +02:00
addr [ i ] = thisflag . cache [ j ] ;
thisflag . cache [ j ] = thisflag . cache [ i ] ;
thisflag . cache [ i ] = addr [ i ] ;
2012-05-25 15:59:10 +02:00
i + + ;
2011-12-20 22:18:13 +01:00
}
2012-05-04 00:08:26 +02:00
return max ;
2011-12-20 05:20:50 +01:00
}
2012-05-04 01:15:49 +02:00
vector < CDnsThread * > dnsThread ;
2011-12-26 01:04:24 +01:00
2012-01-01 19:18:56 +01:00
extern " C " void * ThreadDNS ( void * arg ) {
2012-05-04 01:15:49 +02:00
CDnsThread * thread = ( CDnsThread * ) arg ;
thread - > run ( ) ;
2016-10-29 21:08:46 +02:00
return nullptr ;
2011-12-20 05:20:50 +01:00
}
2012-02-23 18:01:09 +01:00
int StatCompare ( const CAddrReport & a , const CAddrReport & b ) {
if ( a . uptime [ 4 ] = = b . uptime [ 4 ] ) {
if ( a . uptime [ 3 ] = = b . uptime [ 3 ] ) {
return a . clientVersion > b . clientVersion ;
} else {
return a . uptime [ 3 ] > b . uptime [ 3 ] ;
}
} else {
return a . uptime [ 4 ] > b . uptime [ 4 ] ;
}
}
2011-12-20 08:35:22 +01:00
extern " C " void * ThreadDumper ( void * ) {
2013-04-15 12:01:32 +02:00
int count = 0 ;
2011-12-20 08:35:22 +01:00
do {
2013-04-15 12:01:32 +02:00
Sleep ( 100000 < < count ) ; // First 100s, than 200s, 400s, 800s, 1600s, and then 3200s forever
if ( count < 5 )
count + + ;
2011-12-20 08:35:22 +01:00
{
2013-02-24 20:54:53 +01:00
vector < CAddrReport > v = db . GetAll ( ) ;
sort ( v . begin ( ) , v . end ( ) , StatCompare ) ;
2012-09-30 22:02:41 +02:00
FILE * f = fopen ( " dnsseed.dat.new " , " w+ " ) ;
2011-12-20 08:35:22 +01:00
if ( f ) {
2012-09-30 22:02:41 +02:00
{
CAutoFile cf ( f ) ;
cf < < db ;
}
rename ( " dnsseed.dat.new " , " dnsseed.dat " ) ;
2011-12-20 08:35:22 +01:00
}
2012-02-23 18:01:09 +01:00
FILE * d = fopen ( " dnsseed.dump " , " w " ) ;
2016-06-07 18:54:04 +02:00
fprintf ( d , " # address good lastSuccess %%(2h) %%(8h) %%(1d) %%(7d) %%(30d) blocks svcs version \n " ) ;
2012-05-04 00:08:26 +02:00
double stat [ 5 ] = { 0 , 0 , 0 , 0 , 0 } ;
2012-02-23 18:01:09 +01:00
for ( vector < CAddrReport > : : const_iterator it = v . begin ( ) ; it < v . end ( ) ; it + + ) {
CAddrReport rep = * it ;
2016-10-29 21:08:46 +02:00
fprintf ( d , " %-47s %4d %11 " PRId64 " %6.2f%% %6.2f%% %6.2f%% %6.2f%% %6.2f%% %6i %08 " PRIx64 " %5i \" %s \" \n " , rep . ip . ToString ( ) . c_str ( ) , ( int ) rep . fGood , rep . lastSuccess , 100.0 * rep . uptime [ 0 ] , 100.0 * rep . uptime [ 1 ] , 100.0 * rep . uptime [ 2 ] , 100.0 * rep . uptime [ 3 ] , 100.0 * rep . uptime [ 4 ] , rep . blocks , rep . services , rep . clientVersion , rep . clientSubVersion . c_str ( ) ) ;
2012-05-04 00:08:26 +02:00
stat [ 0 ] + = rep . uptime [ 0 ] ;
stat [ 1 ] + = rep . uptime [ 1 ] ;
stat [ 2 ] + = rep . uptime [ 2 ] ;
stat [ 3 ] + = rep . uptime [ 3 ] ;
stat [ 4 ] + = rep . uptime [ 4 ] ;
2012-02-23 18:01:09 +01:00
}
fclose ( d ) ;
2012-05-04 00:08:26 +02:00
FILE * ff = fopen ( " dnsstats.log " , " a " ) ;
fprintf ( ff , " %llu %g %g %g %g %g \n " , ( unsigned long long ) ( time ( NULL ) ) , stat [ 0 ] , stat [ 1 ] , stat [ 2 ] , stat [ 3 ] , stat [ 4 ] ) ;
fclose ( ff ) ;
2011-12-20 08:35:22 +01:00
}
} while ( 1 ) ;
2016-10-29 21:08:46 +02:00
return nullptr ;
2011-12-20 08:35:22 +01:00
}
2011-12-26 01:04:24 +01:00
extern " C " void * ThreadStats ( void * ) {
2012-06-03 18:04:03 +02:00
bool first = true ;
2011-12-26 01:04:24 +01:00
do {
2012-02-23 18:01:09 +01:00
char c [ 256 ] ;
time_t tim = time ( NULL ) ;
struct tm * tmp = localtime ( & tim ) ;
strftime ( c , 256 , " [%y-%m-%d %H:%M:%S] " , tmp ) ;
2011-12-26 01:04:24 +01:00
CAddrDbStats stats ;
db . GetStats ( stats ) ;
2012-06-03 18:04:03 +02:00
if ( first )
{
first = false ;
printf ( " \n \n \n \x1b [3A " ) ;
}
else
printf ( " \x1b [2K \x1b [u " ) ;
printf ( " \x1b [s " ) ;
2012-05-04 01:15:49 +02:00
uint64_t requests = 0 ;
uint64_t queries = 0 ;
for ( unsigned int i = 0 ; i < dnsThread . size ( ) ; i + + ) {
requests + = dnsThread [ i ] - > dns_opt . nRequests ;
queries + = dnsThread [ i ] - > dbQueries ;
}
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 ) ;
2011-12-26 15:53:22 +01:00
Sleep ( 1000 ) ;
2011-12-26 01:04:24 +01:00
} while ( 1 ) ;
2016-10-29 21:08:46 +02:00
return nullptr ;
2011-12-26 01:04:24 +01:00
}
2021-04-12 15:35:35 +02:00
static const string mainnet_seeds [ ] = { " dnsseed1.lbry.io " , " dnsseed2.lbry.io " , " dnsseed3.lbry.io " , " " } ;
static const string testnet_seeds [ ] = { " testdnsseed1.lbry.io " ,
" testdnsseed2.lbry.io " ,
2015-06-21 00:21:06 +02:00
" " } ;
2013-01-24 05:28:07 +01:00
static const string * seeds = mainnet_seeds ;
2011-12-26 01:04:24 +01:00
extern " C " void * ThreadSeeder ( void * ) {
2013-01-24 05:28:07 +01:00
if ( ! fTestNet ) {
db . Add ( CService ( " kjy2eqzk4zwi5zd3.onion " , 8333 ) , true ) ;
}
2011-12-26 01:04:24 +01:00
do {
2013-01-24 05:28:07 +01:00
for ( int i = 0 ; seeds [ i ] ! = " " ; i + + ) {
2012-05-25 15:41:27 +02:00
vector < CNetAddr > ips ;
2011-12-26 01:04:24 +01:00
LookupHost ( seeds [ i ] . c_str ( ) , ips ) ;
2012-05-25 15:41:27 +02:00
for ( vector < CNetAddr > : : iterator it = ips . begin ( ) ; it ! = ips . end ( ) ; it + + ) {
2013-01-24 05:28:07 +01:00
db . Add ( CService ( * it , GetDefaultPort ( ) ) , true ) ;
2011-12-26 01:04:24 +01:00
}
}
Sleep ( 1800000 ) ;
} while ( 1 ) ;
2016-10-29 21:08:46 +02:00
return nullptr ;
2011-12-26 01:04:24 +01:00
}
2012-01-01 19:18:56 +01:00
int main ( int argc , char * * argv ) {
2012-06-21 04:09:05 +02:00
signal ( SIGPIPE , SIG_IGN ) ;
2011-12-26 15:53:22 +01:00
setbuf ( stdout , NULL ) ;
2012-01-01 19:18:56 +01:00
CDnsSeedOpts opts ;
opts . ParseCommandLine ( argc , argv ) ;
2016-06-07 18:54:04 +02:00
printf ( " Supporting whitelisted filters: " ) ;
for ( std : : set < uint64_t > : : const_iterator it = opts . filter_whitelist . begin ( ) ; it ! = opts . filter_whitelist . end ( ) ; it + + ) {
if ( it ! = opts . filter_whitelist . begin ( ) ) {
printf ( " , " ) ;
}
printf ( " 0x%lx " , ( unsigned long ) * it ) ;
}
printf ( " \n " ) ;
2012-10-09 23:26:33 +02:00
if ( opts . tor ) {
CService service ( opts . tor , 9050 ) ;
if ( service . IsValid ( ) ) {
printf ( " Using Tor proxy at %s \n " , service . ToStringIPPort ( ) . c_str ( ) ) ;
SetProxy ( NET_TOR , service ) ;
}
2012-05-30 19:13:00 +02:00
}
2015-07-20 13:48:19 +02:00
if ( opts . ipv4_proxy ) {
CService service ( opts . ipv4_proxy , 9050 ) ;
if ( service . IsValid ( ) ) {
printf ( " Using IPv4 proxy at %s \n " , service . ToStringIPPort ( ) . c_str ( ) ) ;
SetProxy ( NET_IPV4 , service ) ;
}
}
2015-07-26 17:32:05 +02:00
if ( opts . ipv6_proxy ) {
CService service ( opts . ipv6_proxy , 9050 ) ;
if ( service . IsValid ( ) ) {
printf ( " Using IPv6 proxy at %s \n " , service . ToStringIPPort ( ) . c_str ( ) ) ;
SetProxy ( NET_IPV6 , service ) ;
}
}
2012-02-24 01:05:38 +01:00
bool fDNS = true ;
2013-01-24 05:28:07 +01:00
if ( opts . fUseTestNet ) {
printf ( " Using testnet. \n " ) ;
2021-04-12 15:35:35 +02:00
pchMessageStart [ 0 ] = 0xfa ;
pchMessageStart [ 1 ] = 0xe4 ;
pchMessageStart [ 2 ] = 0xaa ;
pchMessageStart [ 3 ] = 0xe1 ;
2013-01-24 05:28:07 +01:00
seeds = testnet_seeds ;
fTestNet = true ;
}
2012-01-01 19:18:56 +01:00
if ( ! opts . ns ) {
2012-02-24 01:05:38 +01:00
printf ( " No nameserver set. Not starting DNS server. \n " ) ;
fDNS = false ;
2012-01-01 19:18:56 +01:00
}
2012-02-24 01:05:38 +01:00
if ( fDNS & & ! opts . host ) {
2012-01-01 19:18:56 +01:00
fprintf ( stderr , " No hostname set. Please use -h. \n " ) ;
2012-01-01 23:23:21 +01:00
exit ( 1 ) ;
2012-01-01 19:18:56 +01:00
}
2015-08-03 21:04:20 +02:00
if ( fDNS & & ! opts . mbox ) {
fprintf ( stderr , " No e-mail address set. Please use -m. \n " ) ;
exit ( 1 ) ;
}
2011-12-20 08:35:22 +01:00
FILE * f = fopen ( " dnsseed.dat " , " r " ) ;
if ( f ) {
2012-01-01 19:18:56 +01:00
printf ( " Loading dnsseed.dat... " ) ;
2011-12-20 08:35:22 +01:00
CAutoFile cf ( f ) ;
cf > > db ;
2012-05-30 19:13:00 +02:00
if ( opts . fWipeBan )
db . banned . clear ( ) ;
if ( opts . fWipeIgnore )
db . ResetIgnores ( ) ;
2012-01-01 19:18:56 +01:00
printf ( " done \n " ) ;
2011-12-20 05:20:50 +01:00
}
2013-04-13 22:37:06 +02:00
pthread_t threadDns , threadSeed , threadDump , threadStats ;
2012-02-24 01:05:38 +01:00
if ( fDNS ) {
2012-05-04 01:15:49 +02:00
printf ( " Starting %i DNS threads for %s on %s (port %i)... " , opts . nDnsThreads , opts . host , opts . ns , opts . nPort ) ;
dnsThread . clear ( ) ;
for ( int i = 0 ; i < opts . nDnsThreads ; i + + ) {
2012-05-26 00:09:07 +02:00
dnsThread . push_back ( new CDnsThread ( & opts , i ) ) ;
2012-05-04 01:15:49 +02:00
pthread_create ( & threadDns , NULL , ThreadDNS , dnsThread [ i ] ) ;
printf ( " . " ) ;
Sleep ( 20 ) ;
}
2012-02-24 01:05:38 +01:00
printf ( " done \n " ) ;
}
2013-04-13 21:56:25 +02:00
printf ( " Starting seeder... " ) ;
pthread_create ( & threadSeed , NULL , ThreadSeeder , NULL ) ;
printf ( " done \n " ) ;
printf ( " Starting %i crawler threads... " , opts . nThreads ) ;
2013-04-17 16:01:25 +02:00
pthread_attr_t attr_crawler ;
pthread_attr_init ( & attr_crawler ) ;
pthread_attr_setstacksize ( & attr_crawler , 0x20000 ) ;
2013-04-13 21:56:25 +02:00
for ( int i = 0 ; i < opts . nThreads ; i + + ) {
pthread_t thread ;
2013-08-09 10:28:52 +02:00
pthread_create ( & thread , & attr_crawler , ThreadCrawler , & opts . nThreads ) ;
2013-04-13 21:56:25 +02:00
}
2013-04-17 16:01:25 +02:00
pthread_attr_destroy ( & attr_crawler ) ;
2013-04-13 21:56:25 +02:00
printf ( " done \n " ) ;
2012-01-01 19:18:56 +01:00
pthread_create ( & threadStats , NULL , ThreadStats , NULL ) ;
2013-04-13 22:46:23 +02:00
pthread_create ( & threadDump , NULL , ThreadDumper , NULL ) ;
2012-01-01 19:18:56 +01:00
void * res ;
2012-02-24 01:05:38 +01:00
pthread_join ( threadDump , & res ) ;
2011-12-20 05:20:50 +01:00
return 0 ;
}