| 1734 | } |
| 1735 | |
| 1736 | void CConnman::ThreadDNSAddressSeed() |
| 1737 | { |
| 1738 | SetSyscallSandboxPolicy(SyscallSandboxPolicy::INITIALIZATION_DNS_SEED); |
| 1739 | FastRandomContext rng; |
| 1740 | std::vector<std::string> seeds = Params().DNSSeeds(); |
| 1741 | Shuffle(seeds.begin(), seeds.end(), rng); |
| 1742 | int seeds_right_now = 0; // Number of seeds left before testing if we have enough connections |
| 1743 | int found = 0; |
| 1744 | |
| 1745 | if (gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED)) { |
| 1746 | // When -forcednsseed is provided, query all. |
| 1747 | seeds_right_now = seeds.size(); |
| 1748 | } else if (addrman.size() == 0) { |
| 1749 | // If we have no known peers, query all. |
| 1750 | // This will occur on the first run, or if peers.dat has been |
| 1751 | // deleted. |
| 1752 | seeds_right_now = seeds.size(); |
| 1753 | } |
| 1754 | |
| 1755 | // goal: only query DNS seed if address need is acute |
| 1756 | // * If we have a reasonable number of peers in addrman, spend |
| 1757 | // some time trying them first. This improves user privacy by |
| 1758 | // creating fewer identifying DNS requests, reduces trust by |
| 1759 | // giving seeds less influence on the network topology, and |
| 1760 | // reduces traffic to the seeds. |
| 1761 | // * When querying DNS seeds query a few at once, this ensures |
| 1762 | // that we don't give DNS seeds the ability to eclipse nodes |
| 1763 | // that query them. |
| 1764 | // * If we continue having problems, eventually query all the |
| 1765 | // DNS seeds, and if that fails too, also try the fixed seeds. |
| 1766 | // (done in ThreadOpenConnections) |
| 1767 | const std::chrono::seconds seeds_wait_time = (addrman.size() >= DNSSEEDS_DELAY_PEER_THRESHOLD ? DNSSEEDS_DELAY_MANY_PEERS : DNSSEEDS_DELAY_FEW_PEERS); |
| 1768 | |
| 1769 | for (const std::string& seed : seeds) { |
| 1770 | if (seeds_right_now == 0) { |
| 1771 | seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE; |
| 1772 | |
| 1773 | if (addrman.size() > 0) { |
| 1774 | LogPrintf("Waiting %d seconds before querying DNS seeds.\n", seeds_wait_time.count()); |
| 1775 | std::chrono::seconds to_wait = seeds_wait_time; |
| 1776 | while (to_wait.count() > 0) { |
| 1777 | // if sleeping for the MANY_PEERS interval, wake up |
| 1778 | // early to see if we have enough peers and can stop |
| 1779 | // this thread entirely freeing up its resources |
| 1780 | std::chrono::seconds w = std::min(DNSSEEDS_DELAY_FEW_PEERS, to_wait); |
| 1781 | if (!interruptNet.sleep_for(w)) return; |
| 1782 | to_wait -= w; |
| 1783 | |
| 1784 | int nRelevant = 0; |
| 1785 | { |
| 1786 | LOCK(m_nodes_mutex); |
| 1787 | for (const CNode* pnode : m_nodes) { |
| 1788 | if (pnode->fSuccessfullyConnected && pnode->IsFullOutboundConn()) ++nRelevant; |
| 1789 | } |
| 1790 | } |
| 1791 | if (nRelevant >= 2) { |
| 1792 | if (found > 0) { |
| 1793 | LogPrintf("%d addresses found from DNS seeds\n", found); |
nothing calls this directly
no test coverage detected