| 692 | } |
| 693 | |
| 694 | std::pair<CAddress, NodeSeconds> AddrManImpl::Select_(bool new_only, const std::unordered_set<Network>& networks) const |
| 695 | { |
| 696 | AssertLockHeld(cs); |
| 697 | |
| 698 | if (vRandom.empty()) return {}; |
| 699 | |
| 700 | size_t new_count = nNew; |
| 701 | size_t tried_count = nTried; |
| 702 | |
| 703 | if (!networks.empty()) { |
| 704 | new_count = 0; |
| 705 | tried_count = 0; |
| 706 | for (auto& network : networks) { |
| 707 | auto it = m_network_counts.find(network); |
| 708 | if (it == m_network_counts.end()) { |
| 709 | continue; |
| 710 | } |
| 711 | auto counts = it->second; |
| 712 | new_count += counts.n_new; |
| 713 | tried_count += counts.n_tried; |
| 714 | } |
| 715 | } |
| 716 | |
| 717 | if (new_only && new_count == 0) return {}; |
| 718 | if (new_count + tried_count == 0) return {}; |
| 719 | |
| 720 | // Decide if we are going to search the new or tried table |
| 721 | // If either option is viable, use a 50% chance to choose |
| 722 | bool search_tried; |
| 723 | if (new_only || tried_count == 0) { |
| 724 | search_tried = false; |
| 725 | } else if (new_count == 0) { |
| 726 | search_tried = true; |
| 727 | } else { |
| 728 | search_tried = insecure_rand.randbool(); |
| 729 | } |
| 730 | |
| 731 | const int bucket_count{search_tried ? ADDRMAN_TRIED_BUCKET_COUNT : ADDRMAN_NEW_BUCKET_COUNT}; |
| 732 | |
| 733 | // Loop through the addrman table until we find an appropriate entry |
| 734 | double chance_factor = 1.0; |
| 735 | while (1) { |
| 736 | // Pick a bucket, and an initial position in that bucket. |
| 737 | int bucket = insecure_rand.randrange(bucket_count); |
| 738 | int initial_position = insecure_rand.randrange(ADDRMAN_BUCKET_SIZE); |
| 739 | |
| 740 | // Iterate over the positions of that bucket, starting at the initial one, |
| 741 | // and looping around. |
| 742 | int i, position; |
| 743 | nid_type node_id; |
| 744 | for (i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) { |
| 745 | position = (initial_position + i) % ADDRMAN_BUCKET_SIZE; |
| 746 | node_id = GetEntry(search_tried, bucket, position); |
| 747 | if (node_id != -1) { |
| 748 | if (!networks.empty()) { |
| 749 | const auto it{mapInfo.find(node_id)}; |
| 750 | if (Assume(it != mapInfo.end()) && networks.contains(it->second.GetNetwork())) break; |
| 751 | } else { |
nothing calls this directly
no test coverage detected