Changeset View
Changeset View
Standalone View
Standalone View
src/seeder/main.cpp
#include <clientversion.h> | #include <clientversion.h> | ||||
#include <fs.h> | #include <fs.h> | ||||
#include <logging.h> | #include <logging.h> | ||||
#include <protocol.h> | #include <protocol.h> | ||||
#include <seeder/bitcoin.h> | #include <seeder/bitcoin.h> | ||||
#include <seeder/db.h> | #include <seeder/db.h> | ||||
#include <seeder/dns.h> | #include <seeder/dns.h> | ||||
#include <streams.h> | #include <streams.h> | ||||
#include <util/strencodings.h> | |||||
#include <util/system.h> | #include <util/system.h> | ||||
#include <algorithm> | #include <algorithm> | ||||
#include <atomic> | #include <atomic> | ||||
#include <cinttypes> | #include <cinttypes> | ||||
#include <csignal> | #include <csignal> | ||||
#include <cstdlib> | #include <cstdlib> | ||||
#include <getopt.h> | |||||
#include <pthread.h> | #include <pthread.h> | ||||
const std::function<std::string(const char *)> G_TRANSLATION_FUN = nullptr; | const std::function<std::string(const char *)> G_TRANSLATION_FUN = nullptr; | ||||
static const int DEFAULT_NUM_THREADS = 96; | static const int DEFAULT_NUM_THREADS = 96; | ||||
static const int DEFAULT_PORT = 53; | static const int DEFAULT_PORT = 53; | ||||
static const int DEFAULT_NUM_DNS_THREADS = 4; | static const int DEFAULT_NUM_DNS_THREADS = 4; | ||||
static const bool DEFAULT_TESTNET = false; | static const bool DEFAULT_TESTNET = false; | ||||
static const bool DEFAULT_WIPE_BAN = false; | static const bool DEFAULT_WIPE_BAN = false; | ||||
static const bool DEFAULT_WIPE_IGNORE = false; | static const bool DEFAULT_WIPE_IGNORE = false; | ||||
static const std::string DEFAULT_EMAIL = ""; | static const std::string DEFAULT_EMAIL = ""; | ||||
static const std::string DEFAULT_NAMESERVER = ""; | static const std::string DEFAULT_NAMESERVER = ""; | ||||
static const std::string DEFAULT_HOST = ""; | static const std::string DEFAULT_HOST = ""; | ||||
static const std::string DEFAULT_TOR_PROXY = ""; | static const std::string DEFAULT_TOR_PROXY = ""; | ||||
static const std::string DEFAULT_IPV4_PROXY = ""; | static const std::string DEFAULT_IPV4_PROXY = ""; | ||||
static const std::string DEFAULT_IPV6_PROXY = ""; | static const std::string DEFAULT_IPV6_PROXY = ""; | ||||
class CDnsSeedOpts { | class CDnsSeedOpts { | ||||
public: | public: | ||||
int nThreads; | int nThreads; | ||||
int nPort; | int nPort; | ||||
int nDnsThreads; | int nDnsThreads; | ||||
int fUseTestNet; | bool fUseTestNet; | ||||
int fWipeBan; | bool fWipeBan; | ||||
int fWipeIgnore; | bool fWipeIgnore; | ||||
std::string mbox; | std::string mbox; | ||||
std::string ns; | std::string ns; | ||||
std::string host; | std::string host; | ||||
std::string tor; | std::string tor; | ||||
std::string ipv4_proxy; | std::string ipv4_proxy; | ||||
std::string ipv6_proxy; | std::string ipv6_proxy; | ||||
std::set<uint64_t> filter_whitelist; | std::set<uint64_t> filter_whitelist; | ||||
CDnsSeedOpts() | CDnsSeedOpts() | ||||
: nThreads(DEFAULT_NUM_THREADS), nPort(DEFAULT_PORT), | : nThreads(DEFAULT_NUM_THREADS), nPort(DEFAULT_PORT), | ||||
nDnsThreads(DEFAULT_NUM_DNS_THREADS), fUseTestNet(DEFAULT_TESTNET), | nDnsThreads(DEFAULT_NUM_DNS_THREADS), fUseTestNet(DEFAULT_TESTNET), | ||||
fWipeBan(DEFAULT_WIPE_BAN), fWipeIgnore(DEFAULT_WIPE_IGNORE), | fWipeBan(DEFAULT_WIPE_BAN), fWipeIgnore(DEFAULT_WIPE_IGNORE), | ||||
mbox(DEFAULT_EMAIL), ns(DEFAULT_NAMESERVER), host(DEFAULT_HOST), | mbox(DEFAULT_EMAIL), ns(DEFAULT_NAMESERVER), host(DEFAULT_HOST), | ||||
tor(DEFAULT_TOR_PROXY), ipv4_proxy(DEFAULT_IPV4_PROXY), | tor(DEFAULT_TOR_PROXY), ipv4_proxy(DEFAULT_IPV4_PROXY), | ||||
ipv6_proxy(DEFAULT_IPV6_PROXY) {} | ipv6_proxy(DEFAULT_IPV6_PROXY) {} | ||||
void ParseCommandLine(int argc, char **argv) { | void ParseCommandLine(int argc, char **argv) { | ||||
static const char *help = | std::string error; | ||||
"Bitcoin-cash-seeder\n" | if (!gArgs.ParseParameters(argc, argv, error)) { | ||||
"Usage: %s -h <host> -n <ns> [-m <mbox>] [-t <threads>] [-p " | fprintf(stderr, "Error parsing command line arguments: %s\n", | ||||
"<port>]\n" | error.c_str()); | ||||
"\n" | exit(1); | ||||
deadalnix: This function never exited before. It is generally not the best idea to abruptly exit anywhere. | |||||
"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" | |||||
"-t <threads> Number of crawlers to run in parallel (default " | |||||
"96)\n" | |||||
"-d <threads> Number of DNS server threads (default 4)\n" | |||||
"-p <port> UDP port to listen on (default 53)\n" | |||||
"-o <ip:port> Tor proxy IP/Port\n" | |||||
"-i <ip:port> IPV4 SOCKS5 proxy IP/Port\n" | |||||
"-k <ip:port> IPV6 SOCKS5 proxy IP/Port\n" | |||||
"-w f1,f2,... Allow these flag combinations as filters\n" | |||||
"--testnet Use testnet\n" | |||||
"--wipeban Wipe list of banned nodes\n" | |||||
"--wipeignore Wipe list of ignored nodes\n" | |||||
"-?, --help Show this text\n" | |||||
"\n"; | |||||
bool showHelp = false; | |||||
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'}, | |||||
{"dnsthreads", required_argument, 0, 'd'}, | |||||
{"port", required_argument, 0, 'p'}, | |||||
{"onion", required_argument, 0, 'o'}, | |||||
{"proxyipv4", required_argument, 0, 'i'}, | |||||
{"proxyipv6", required_argument, 0, 'k'}, | |||||
{"filter", required_argument, 0, 'w'}, | |||||
{"testnet", no_argument, &fUseTestNet, 1}, | |||||
{"wipeban", no_argument, &fWipeBan, 1}, | |||||
{"wipeignore", no_argument, &fWipeIgnore, 1}, | |||||
{"help", no_argument, 0, 'h'}, | |||||
{0, 0, 0, 0}}; | |||||
int option_index = 0; | |||||
int c = | |||||
getopt_long(argc, argv, "h:n:m:t:p:d:o:i:k:w:", long_options, | |||||
&option_index); | |||||
if (c == -1) break; | |||||
switch (c) { | |||||
case 'h': { | |||||
host = std::string(optarg); | |||||
break; | |||||
} | |||||
case 'm': { | |||||
mbox = std::string(optarg); | |||||
break; | |||||
} | |||||
case 'n': { | |||||
ns = std::string(optarg); | |||||
break; | |||||
} | |||||
case 't': { | |||||
int n = strtol(optarg, nullptr, 10); | |||||
if (n > 0 && n < 1000) nThreads = n; | |||||
break; | |||||
} | |||||
case 'd': { | |||||
int n = strtol(optarg, nullptr, 10); | |||||
if (n > 0 && n < 1000) nDnsThreads = n; | |||||
break; | |||||
} | |||||
case 'p': { | |||||
int p = strtol(optarg, nullptr, 10); | |||||
if (p > 0 && p < 65536) nPort = p; | |||||
break; | |||||
} | |||||
case 'o': { | |||||
tor = std::string(optarg); | |||||
break; | |||||
} | |||||
case 'i': { | |||||
ipv4_proxy = std::string(optarg); | |||||
break; | |||||
} | |||||
case 'k': { | |||||
ipv6_proxy = std::string(optarg); | |||||
break; | |||||
} | |||||
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); | |||||
} | } | ||||
if (HelpRequested(gArgs)) { | |||||
std::string strUsage = "Bitcoin-cash-seeder\nUsage: bitcoin-seeder " | |||||
"-host=<host> -ns=<ns> [-mbox=<mbox>] " | |||||
"[-threads=<threads>] [-port=<port>]\n\n" + | |||||
gArgs.GetHelpMessage(); | |||||
fprintf(stdout, "%s", strUsage.c_str()); | |||||
exit(0); | |||||
} | |||||
nThreads = gArgs.GetArg("-threads", DEFAULT_NUM_THREADS); | |||||
nPort = gArgs.GetArg("-port", DEFAULT_PORT); | |||||
nDnsThreads = gArgs.GetArg("-dnsthreads", DEFAULT_NUM_DNS_THREADS); | |||||
fUseTestNet = gArgs.GetBoolArg("-testnet", DEFAULT_TESTNET); | |||||
fWipeBan = gArgs.GetBoolArg("-wipeban", DEFAULT_WIPE_BAN); | |||||
fWipeIgnore = gArgs.GetBoolArg("-wipeignore", DEFAULT_WIPE_IGNORE); | |||||
mbox = gArgs.GetArg("-mbox", DEFAULT_EMAIL); | |||||
ns = gArgs.GetArg("-ns", DEFAULT_NAMESERVER); | |||||
host = gArgs.GetArg("-host", DEFAULT_HOST); | |||||
tor = gArgs.GetArg("-onion", DEFAULT_TOR_PROXY); | |||||
ipv4_proxy = gArgs.GetArg("-proxyipv4", DEFAULT_IPV4_PROXY); | |||||
ipv6_proxy = gArgs.GetArg("-proxyipv6", DEFAULT_IPV6_PROXY); | |||||
if (gArgs.IsArgSet("-filter")) { | |||||
// Parse whitelist additions | |||||
std::string flags = gArgs.GetArg("-filter", ""); | |||||
size_t flagstartpos = 0; | |||||
while (flagstartpos < flags.size()) { | |||||
size_t flagendpos = flags.find_first_of(",", flagstartpos); | |||||
deadalnixUnsubmitted Not Done Inline ActionsYou did something recently involving this kind of patterns. deadalnix: You did something recently involving this kind of patterns. | |||||
uint64_t flag = atoi64( | |||||
flags.substr(flagstartpos, (flagendpos - flagstartpos))); | |||||
filter_whitelist.insert(flag); | |||||
if (flagendpos == std::string::npos) { | |||||
break; | break; | ||||
} | } | ||||
flagstartpos = flagendpos + 1; | |||||
case '?': { | |||||
showHelp = true; | |||||
break; | |||||
} | |||||
} | } | ||||
} | } | ||||
if (filter_whitelist.empty()) { | if (filter_whitelist.empty()) { | ||||
filter_whitelist.insert(NODE_NETWORK); | filter_whitelist.insert(NODE_NETWORK); | ||||
filter_whitelist.insert(NODE_NETWORK | NODE_BLOOM); | filter_whitelist.insert(NODE_NETWORK | NODE_BLOOM); | ||||
filter_whitelist.insert(NODE_NETWORK | NODE_XTHIN); | filter_whitelist.insert(NODE_NETWORK | NODE_XTHIN); | ||||
filter_whitelist.insert(NODE_NETWORK | NODE_BLOOM | NODE_XTHIN); | filter_whitelist.insert(NODE_NETWORK | NODE_BLOOM | NODE_XTHIN); | ||||
} | } | ||||
if (!host.empty() && ns.empty()) showHelp = true; | |||||
if (showHelp) fprintf(stderr, help, argv[0]); | |||||
} | } | ||||
}; | }; | ||||
extern "C" { | extern "C" { | ||||
#include <seeder/dns.h> | #include <seeder/dns.h> | ||||
} | } | ||||
CAddrDb db; | CAddrDb db; | ||||
▲ Show 20 Lines • Show All 292 Lines • ▼ Show 20 Lines | do { | ||||
true); | true); | ||||
} | } | ||||
} | } | ||||
Sleep(1800000); | Sleep(1800000); | ||||
} while (1); | } while (1); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
static void SetupSeederArgs() { | |||||
gArgs.AddArg("-?", _("Print this help message and exit"), false, | |||||
OptionsCategory::OPTIONS); | |||||
gArgs.AddArg("-host=<host>", _("Hostname of the DNS seed"), false, | |||||
OptionsCategory::OPTIONS); | |||||
gArgs.AddArg("-ns=<ns>", _("Hostname of the nameserver"), false, | |||||
OptionsCategory::OPTIONS); | |||||
gArgs.AddArg("-mbox=<mbox>", _("E-Mail address reported in SOA records"), | |||||
false, OptionsCategory::OPTIONS); | |||||
gArgs.AddArg("-threads=<threads>", | |||||
_("Number of crawlers to run in parallel (default 96)"), false, | |||||
OptionsCategory::OPTIONS); | |||||
gArgs.AddArg("-dnsthreads=<threads>", | |||||
_("Number of DNS server threads (default 4)"), false, | |||||
OptionsCategory::OPTIONS); | |||||
gArgs.AddArg("-port=<port>", _("UDP port to listen on (default 53)"), false, | |||||
OptionsCategory::CONNECTION); | |||||
gArgs.AddArg("-onion=<ip:port>", _("Tor proxy IP/Port"), false, | |||||
OptionsCategory::CONNECTION); | |||||
gArgs.AddArg("-proxyipv4=<ip:port>", _("IPV4 SOCKS5 proxy IP/Port"), false, | |||||
OptionsCategory::CONNECTION); | |||||
gArgs.AddArg("-proxyipv6=<ip:port>", _("IPV6 SOCKS5 proxy IP/Port"), false, | |||||
OptionsCategory::CONNECTION); | |||||
gArgs.AddArg("-filter=<f1,f2,...>", | |||||
_("Allow these flag combinations as filters"), false, | |||||
OptionsCategory::OPTIONS); | |||||
gArgs.AddArg("-testnet", _("Use testnet"), false, | |||||
OptionsCategory::CHAINPARAMS); | |||||
gArgs.AddArg("-wipeban", _("Wipe list of banned nodes"), false, | |||||
OptionsCategory::CONNECTION); | |||||
gArgs.AddArg("-wipeignore", _("Wipe list of ignored nodes"), false, | |||||
OptionsCategory::CONNECTION); | |||||
gArgs.AddArg("-help", "", false, OptionsCategory::HIDDEN); | |||||
gArgs.AddArg("-h", "", false, OptionsCategory::HIDDEN); | |||||
} | |||||
int main(int argc, char **argv) { | int main(int argc, char **argv) { | ||||
// The logger dump everything on the console by default. | // The logger dump everything on the console by default. | ||||
GetLogger().m_print_to_console = true; | GetLogger().m_print_to_console = true; | ||||
signal(SIGPIPE, SIG_IGN); | signal(SIGPIPE, SIG_IGN); | ||||
setbuf(stdout, nullptr); | setbuf(stdout, nullptr); | ||||
CDnsSeedOpts opts; | CDnsSeedOpts opts; | ||||
SetupSeederArgs(); | |||||
deadalnixUnsubmitted Not Done Inline ActionsIt is somewhat strange that the args need to be setup here, when they are parsed somewhere else. This doesn't match how other application we have are doing it. Why the new pattern? deadalnix: It is somewhat strange that the args need to be setup here, when they are parsed somewhere else. | |||||
nakihitoAuthorUnsubmitted Done Inline ActionsYou're correct. After thinking about it, I can see that I am skipping a step here. I've moved the function to the CDnsSeedOpts class. nakihito: You're correct. After thinking about it, I can see that I am skipping a step here. I've moved… | |||||
opts.ParseCommandLine(argc, argv); | opts.ParseCommandLine(argc, argv); | ||||
fprintf(stdout, "Supporting whitelisted filters: "); | fprintf(stdout, "Supporting whitelisted filters: "); | ||||
for (std::set<uint64_t>::const_iterator it = opts.filter_whitelist.begin(); | for (std::set<uint64_t>::const_iterator it = opts.filter_whitelist.begin(); | ||||
it != opts.filter_whitelist.end(); it++) { | it != opts.filter_whitelist.end(); it++) { | ||||
if (it != opts.filter_whitelist.begin()) { | if (it != opts.filter_whitelist.begin()) { | ||||
fprintf(stdout, ","); | fprintf(stdout, ","); | ||||
} | } | ||||
fprintf(stdout, "0x%lx", (unsigned long)*it); | fprintf(stdout, "0x%lx", (unsigned long)*it); | ||||
▲ Show 20 Lines • Show All 96 Lines • Show Last 20 Lines |
This function never exited before. It is generally not the best idea to abruptly exit anywhere.
looked into several of the existing application, and this isn't how they do it. What the benefit of using this new pattern?