/* * This file is part of the Flowee project * Copyright (C) 2020-2023 Tom Zander * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "FillAddressDBAction.h" #include "DownloadManager.h" #include "ConnectionManager.h" #include "PeerAddressDB.h" #include "Peer.h" #include #include static int PORTNR = 8333; static std::vector fillSeeders(P2PNet::Chain chain) { std::vector answer; switch (chain) { case P2PNet::MainChain: answer.push_back("seed.flowee.cash"); answer.push_back("bchseed.c3-soft.com"); answer.push_back("bch.bitjson.com"); break; case P2PNet::Testnet4Chain: answer.push_back("testnet4-seed.flowee.cash"); answer.push_back("testnet4.bitjson.com"); PORTNR = 28333; break; } return answer; } static int s_minAddressEntries = 2000; FillAddressDBAction::FillAddressDBAction(DownloadManager *parent) : Action(parent), m_resolver(parent->ioContext()), m_seeders(fillSeeders(parent->chain())) { assert(!m_seeders.empty()); if (parent->chain() != P2PNet::MainChain) s_minAddressEntries = 25; } void FillAddressDBAction::execute(const boost::system::error_code &error) { if (error) return; if ((m_dnsLookupState % 2) != 1) { // start a new DNS lookup? const size_t index = m_dnsLookupState / 2; if (index == m_seeders.size()) { logInfo() << "Asked all DNS seeds"; } else if (index < m_seeders.size()) { m_dnsLookupState++; logInfo() << "Start to resolve DNS entry" << m_seeders.at(index); const std::string port = strprintf("%d", PORTNR); m_resolver.async_resolve(m_seeders.at(index), port, std::bind(&FillAddressDBAction::onAddressResolveComplete, this, std::placeholders::_1, std::placeholders::_2)); again(); return; } } if ((m_dnsLookupState % 2) == 0) { // not running a DNS lookup right now. if (m_dlm->connectionManager().peerAddressDb().peerCount() > s_minAddressEntries) { logInfo() << "==== FillAddressDb ==== DONE"; m_dlm->done(this); return; } } for (auto peer : m_dlm->connectionManager().connectedPeers()) { auto address = peer->peerAddress(); if (address.isValid() && address.lastReceivedGoodHeaders()) { if (!address.askedAddresses()) { address.setAskedAddresses(true); logInfo() << "Sending GetAddr msg to" << peer->connectionId(); peer->sendMessage(Message(Api::LegacyP2P, Api::P2P::GetAddr)); m_lastRequestStarted = time(nullptr); again(); return; } } } if (m_lastRequestStarted > 0 && static_cast(time(nullptr)) - m_lastRequestStarted < 60) { again(); return; } // lets connect to some new peers then. auto address = m_dlm->connectionManager().peerAddressDb().findBest(); if (address.isValid()) { logInfo() << "AddressDB still needs more data: creating a new connection"; m_dlm->connectionManager().connect(address); } again(); } void FillAddressDBAction::onAddressResolveComplete(const boost::system::error_code &error, boost::asio::ip::tcp::resolver::results_type results) { if (error.value() == boost::asio::error::operation_aborted) // this means the app is shutting down. return; int count = 0; if (!error) { auto iter = results.cbegin(); while (iter != results.cend()) { EndPoint ep(iter->endpoint().address(), PORTNR); ++count; m_dlm->connectionManager().peerAddressDb().addOne(ep); iter++; } } logInfo() << "DNS resolve came back. Success:" << !((bool) error) << "Result count:" << count; m_dnsLookupState++; }