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>
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 ;
2015-07-20 13:48:19 +02:00
const char * ipv4_proxy ;
2015-07-26 17:32:05 +02:00
const char * ipv6_proxy ;
2013-04-13 21:45:52 +02:00
2015-07-29 15:33:33 +02:00
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 ) { }
2013-04-13 21:45:52 +02:00
2012-01-01 19:18:56 +01:00
void ParseCommandLine ( int argc , char * * argv ) {
2012-01-01 23:23:21 +01:00
static const char * help = " Bitcoin-seeder \n "
" 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 "
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 "
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 ' } ,
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 ' } ,
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 ;
2015-07-26 17:32:05 +02:00
int c = getopt_long ( argc , argv , " h:n:m:t:p:d:o:i:k: " , long_options , & option_index ) ;
2012-01-01 19:18:56 +01:00
if ( c = = - 1 ) break ;
switch ( c ) {
case ' h ' : {
host = optarg ;
break ;
}
case ' m ' : {
mbox = optarg ;
break ;
}
case ' n ' : {
ns = optarg ;
break ;
}
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 ;
}
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 ;
}
2012-01-01 23:23:21 +01:00
case ' ? ' : {
showHelp = true ;
break ;
2012-01-01 19:18:56 +01: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 05:20:50 +01:00
extern " C " {
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 = " " ;
2013-04-25 01:55:26 +02:00
bool getaddr = res . ourLastSuccess + 604800 < now ;
res . fGood = TestNode ( res . service , res . nBanTime , res . nClientV , res . strClientV , res . nHeight , getaddr ? & addr : NULL ) ;
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 ) ;
}
2012-05-25 15:41:27 +02:00
extern " C " int GetIPList ( void * thread , 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 :
2012-05-26 00:09:07 +02:00
dns_opt_t dns_opt ; // must be first
const int id ;
2012-05-25 15:41:27 +02:00
vector < addr_t > cache ;
int nIPv4 , nIPv6 ;
2012-05-04 01:15:49 +02:00
time_t cacheTime ;
unsigned int cacheHits ;
uint64_t dbQueries ;
2012-05-25 15:41:27 +02:00
void cacheHit ( bool force = false ) {
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 ) ;
cacheHits + + ;
if ( force | | cacheHits > ( cache . size ( ) * cache . size ( ) / 400 ) | | ( cacheHits * cacheHits > cache . size ( ) / 20 & & ( now - cacheTime > 5 ) ) ) {
2012-05-25 15:41:27 +02:00
set < CNetAddr > ips ;
db . GetIPs ( ips , 1000 , nets ) ;
2012-05-04 01:15:49 +02:00
dbQueries + + ;
cache . clear ( ) ;
2012-05-25 15:41:27 +02:00
nIPv4 = 0 ;
nIPv6 = 0 ;
2012-05-04 01:15:49 +02:00
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 ) ;
cache . push_back ( a ) ;
nIPv4 + + ;
} else if ( ( * it ) . GetIn6Addr ( & addr6 ) ) {
addr_t a ;
a . v = 6 ;
memcpy ( & a . data . v6 , & addr6 , 16 ) ;
cache . push_back ( a ) ;
nIPv6 + + ;
2012-05-04 01:15:49 +02:00
}
2012-05-04 00:08:26 +02:00
}
2012-05-04 01:15:49 +02:00
cacheHits = 0 ;
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 ;
dns_opt . datattl = 60 ;
dns_opt . nsttl = 40000 ;
dns_opt . cb = GetIPList ;
dns_opt . port = opts - > nPort ;
dns_opt . nRequests = 0 ;
cache . clear ( ) ;
cache . reserve ( 1000 ) ;
cacheTime = 0 ;
2012-05-04 00:08:26 +02:00
cacheHits = 0 ;
2012-05-04 01:15:49 +02:00
dbQueries = 0 ;
2012-05-25 15:41:27 +02:00
nIPv4 = 0 ;
nIPv6 = 0 ;
cacheHit ( true ) ;
2012-05-04 00:08:26 +02:00
}
2012-05-04 01:15:49 +02:00
void run ( ) {
dnsserver ( & dns_opt ) ;
}
} ;
2012-05-25 15:41:27 +02:00
extern " C " int GetIPList ( void * data , addr_t * addr , int max , int ipv4 , int ipv6 ) {
2012-05-04 01:15:49 +02:00
CDnsThread * thread = ( CDnsThread * ) data ;
2012-05-25 15:41:27 +02:00
thread - > cacheHit ( ) ;
2012-05-26 00:09:07 +02:00
unsigned int size = thread - > cache . size ( ) ;
unsigned int maxmax = ( ipv4 ? thread - > nIPv4 : 0 ) + ( ipv6 ? thread - > 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 {
bool ok = ( ipv4 & & thread - > cache [ j ] . v = = 4 ) | |
( ipv6 & & thread - > cache [ j ] . v = = 6 ) ;
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 ) ;
2012-05-04 01:15:49 +02:00
addr [ i ] = thread - > cache [ j ] ;
thread - > cache [ j ] = thread - > cache [ i ] ;
thread - > 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 ( ) ;
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 " ) ;
2013-04-15 14:45:31 +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 ;
2013-04-15 14:45:31 +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 ) ;
}
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 ) ;
}
2013-01-24 05:28:07 +01:00
static const string mainnet_seeds [ ] = { " dnsseed.bluematt.me " , " bitseed.xf2.org " , " dnsseed.bitcoin.dashjr.org " , " seed.bitcoin.sipa.be " , " " } ;
2015-06-21 00:21:06 +02:00
static const string testnet_seeds [ ] = { " testnet-seed.alexykot.me " ,
" testnet-seed.bitcoin.petertodd.org " ,
" testnet-seed.bluematt.me " ,
" testnet-seed.bitcoin.schildbach.de " ,
" " } ;
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 ) ;
}
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 ) ;
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 " ) ;
pchMessageStart [ 0 ] = 0x0b ;
pchMessageStart [ 1 ] = 0x11 ;
pchMessageStart [ 2 ] = 0x09 ;
pchMessageStart [ 3 ] = 0x07 ;
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
}
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 ;
}