lokinet/daemon/lokinet-bootstrap.cpp

108 lines
2.8 KiB
C++
Raw Normal View History

2021-04-15 17:39:45 +00:00
#include <llarp/constants/files.hpp>
#include <llarp/constants/version.hpp>
#include <llarp/util/fs.hpp>
#include <cpr/cpr.h>
#include <iostream>
#include <unordered_map>
#include <unordered_set>
2021-04-15 17:39:45 +00:00
#ifndef _WIN32
#include <openssl/x509.h>
#endif
namespace
{
2024-02-01 12:43:43 +00:00
int fail(std::string msg)
{
std::cout << msg << std::endl;
return 1;
}
int print_help(std::string exe)
{
std::cout << R"(Lokinet bootstrap.signed fetchy program thing
2021-09-08 22:48:25 +00:00
Downloads the initial bootstrap.signed for lokinet into a local file from a
default or user defined server via the reachable network.
2024-02-01 12:43:43 +00:00
Usage: )" << exe << R"( [bootstrap_url [output_file]]
2021-09-08 22:48:25 +00:00
bootstrap_url can be specified as a full URL, or a special named value
("mainnet" or "testnet") to download from the pre-defined mainnet or testnet
bootstrap URLs.
)";
2024-02-01 12:43:43 +00:00
return 0;
}
2021-04-15 17:39:45 +00:00
} // namespace
2024-02-01 12:43:43 +00:00
int main(int argc, char* argv[])
2021-04-15 17:39:45 +00:00
{
2024-02-01 12:43:43 +00:00
const std::unordered_map<std::string, std::string> bootstrap_urls = {
2024-02-02 20:50:48 +00:00
{"lokinet", "https://seed.lokinet.org/lokinet.signed"}, {"testnet", "https://seed.lokinet.org/testnet.signed"}};
2024-02-01 12:43:43 +00:00
std::string bootstrap_url = bootstrap_urls.at("lokinet");
fs::path outputfile{llarp::GetDefaultBootstrap()};
2024-02-01 12:43:43 +00:00
const std::unordered_set<std::string> help_args = {"-h", "--help"};
2024-02-01 12:43:43 +00:00
for (int idx = 1; idx < argc; idx++)
{
const std::string arg{argv[idx]};
if (help_args.count(arg))
return print_help(argv[0]);
}
2024-02-01 12:43:43 +00:00
if (argc > 1)
{
2024-02-01 12:43:43 +00:00
if (auto itr = bootstrap_urls.find(argv[1]); itr != bootstrap_urls.end())
{
bootstrap_url = itr->second;
}
else
{
bootstrap_url = argv[1];
}
}
2024-02-01 12:43:43 +00:00
if (argc > 2)
{
2024-02-01 12:43:43 +00:00
outputfile = fs::path{argv[2]};
}
2024-02-01 12:43:43 +00:00
std::cout << "fetching " << bootstrap_url << std::endl;
cpr::Response resp =
2021-04-15 17:39:45 +00:00
#ifdef _WIN32
2024-02-02 20:50:48 +00:00
cpr::Get(cpr::Url{bootstrap_url}, cpr::Header{{"User-Agent", std::string{llarp::VERSION_FULL}}});
2021-04-15 17:39:45 +00:00
#else
2024-02-01 12:43:43 +00:00
cpr::Get(
cpr::Url{bootstrap_url},
cpr::Header{{"User-Agent", std::string{llarp::LOKINET_VERSION_FULL}}},
cpr::Ssl(cpr::ssl::CaPath{X509_get_default_cert_dir()}));
2021-04-15 17:39:45 +00:00
#endif
2024-02-01 12:43:43 +00:00
if (resp.status_code != 200)
2021-04-16 19:01:00 +00:00
{
2024-02-02 20:50:48 +00:00
return fail("failed to fetch '" + bootstrap_url + "' HTTP " + std::to_string(resp.status_code));
2021-04-16 19:01:00 +00:00
}
2024-02-01 12:43:43 +00:00
const auto& data = resp.text;
if (data[0] == 'l' or data[0] == 'd')
2021-04-16 19:01:00 +00:00
{
2024-02-01 12:43:43 +00:00
try
{
std::cout << "writing bootstrap file to: " << outputfile << std::endl;
fs::ofstream ofs{outputfile, std::ios::binary};
ofs.exceptions(fs::ofstream::failbit);
ofs << data;
return 0;
}
catch (std::exception& ex)
{
return fail(std::string{"failed to write bootstrap file: "} + ex.what());
}
2021-04-16 19:01:00 +00:00
}
2024-02-01 12:43:43 +00:00
return fail("got invalid bootstrap file content");
2021-04-15 17:39:45 +00:00
}