Skip to content

Commit

Permalink
Merge release/cuttlefish into main (#1039)
Browse files Browse the repository at this point in the history
  • Loading branch information
iamyulong authored Dec 2, 2024
2 parents 0b08f3c + 7440dd4 commit 4498e16
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 65 deletions.
58 changes: 27 additions & 31 deletions core/src/main/java/com/radixdlt/p2p/hostip/NetworkQueryHostIp.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@
import com.radixdlt.lang.Result;
import com.radixdlt.utils.properties.RuntimeProperties;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand All @@ -98,21 +96,21 @@ final class NetworkQueryHostIp {

public record VotedResult(
Optional<HostIp> conclusiveHostIp,
ImmutableMap<URL, Result<HostIp, IOException>> individualQueryResults) {}
ImmutableMap<String, Result<HostIp, IOException>> individualQueryResults) {}

@VisibleForTesting static final String QUERY_URLS_PROPERTY = "network.host_ip_query_urls";

@VisibleForTesting
static final ImmutableList<URL> DEFAULT_QUERY_URLS =
static final ImmutableList<String> DEFAULT_QUERY_URLS =
ImmutableList.of(
makeurl("https://checkip.amazonaws.com/"),
makeurl("https://ipv4.icanhazip.com/"),
makeurl("https://myexternalip.com/raw"),
makeurl("https://ipecho.net/plain"),
makeurl("https://www.trackip.net/ip"),
makeurl("https://ifconfig.co/ip"));

static NetworkQueryHostIp create(Collection<URL> urls) {
"https://checkip.amazonaws.com/",
"https://ipv4.icanhazip.com/",
"https://myexternalip.com/raw",
"https://ipecho.net/plain",
"https://www.trackip.net/ip",
"https://ifconfig.co/ip");

static NetworkQueryHostIp create(Collection<String> urls) {
return new NetworkQueryHostIp(urls);
}

Expand All @@ -121,18 +119,20 @@ static NetworkQueryHostIp create(RuntimeProperties properties) {
if (urlsProperty == null || urlsProperty.trim().isEmpty()) {
return create(DEFAULT_QUERY_URLS);
}
ImmutableList<URL> urls =
Arrays.asList(urlsProperty.split(",")).stream()
.map(NetworkQueryHostIp::makeurl)
.collect(ImmutableList.toImmutableList());
ImmutableList<String> urls =
Arrays.asList(urlsProperty.split(",")).stream().collect(ImmutableList.toImmutableList());
return create(urls);
}

private final List<URL> hosts;
private final List<String> hosts;
private final OkHttpClient okHttpClient;
private final Supplier<VotedResult> result = Suppliers.memoize(this::get);

NetworkQueryHostIp(Collection<URL> urls) {
NetworkQueryHostIp() {
this(DEFAULT_QUERY_URLS);
}

NetworkQueryHostIp(Collection<String> urls) {
if (urls.isEmpty()) {
throw new IllegalArgumentException("At least one URL must be specified");
}
Expand All @@ -144,20 +144,24 @@ int count() {
return this.hosts.size();
}

List<String> hosts() {
return this.hosts;
}

public VotedResult queryNetworkHosts() {
return result.get();
}

VotedResult get() {
// Make sure we don't DoS the first one on the list
Collections.shuffle(this.hosts);
log.debug("Using hosts {}", this.hosts);
Collections.shuffle(this.hosts());
log.debug("Using hosts {}", this.hosts());
final Map<HostIp, AtomicInteger> successCounts = Maps.newHashMap();
final ImmutableMap.Builder<URL, Result<HostIp, IOException>> queryResults =
final ImmutableMap.Builder<String, Result<HostIp, IOException>> queryResults =
ImmutableMap.builder();
int maxCount = 0;
Optional<HostIp> maxResult = Optional.empty();
for (URL url : this.hosts) {
for (String url : this.hosts()) {
final Result<HostIp, IOException> result = query(url);
queryResults.put(url, result);
if (result.isSuccess()) {
Expand Down Expand Up @@ -191,7 +195,7 @@ VotedResult get() {
return new VotedResult(maxResult, queryResults.build());
}

Result<HostIp, IOException> query(URL url) {
Result<HostIp, IOException> query(String url) {
try {
// Some services simply require the headers we set here:
final var request =
Expand All @@ -214,12 +218,4 @@ Result<HostIp, IOException> query(URL url) {
return Result.error(ex);
}
}

private static URL makeurl(String s) {
try {
return new URL(s);
} catch (MalformedURLException ex) {
throw new IllegalStateException("While constructing URL for " + s, ex);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,19 @@
package com.radixdlt.p2p.hostip;

import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;

import com.radixdlt.lang.Result;
import com.radixdlt.utils.properties.RuntimeProperties;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.junit.Test;
import org.mockito.Mockito;

public class NetworkQueryHostIpTest {

Expand Down Expand Up @@ -112,43 +113,31 @@ public void testCollectionEmpty() {

@Test
public void testCollectionNotEmptyQueryNotSuccessful() throws IOException {
NetworkQueryHostIp nqhip = NetworkQueryHostIp.create(List.of(makeUrl(404, "not found")));
Optional<HostIp> host = nqhip.queryNetworkHosts().conclusiveHostIp();
assertFalse(host.isPresent());
}

@Test
public void testCollectionNotEmptyQueryIoException() throws IOException {
URL url = mock(URL.class);
doReturn("https://mock.url/with-io-problems").when(url).toString();
doThrow(new IOException("test exception")).when(url).openConnection();
NetworkQueryHostIp nqhip = NetworkQueryHostIp.create(List.of(url));
NetworkQueryHostIp nqhip =
makeNetworkQueryHostIp(Map.of("a", Result.error(new IOException(""))));
Optional<HostIp> host = nqhip.queryNetworkHosts().conclusiveHostIp();
assertFalse(host.isPresent());
}

@Test
public void testCollectionAllDifferent() throws IOException {
List<URL> urls =
List.of(
makeUrl(200, "127.0.0.1"),
makeUrl(200, "127.0.0.2"),
makeUrl(200, "127.0.0.3"),
makeUrl(200, "127.0.0.4"));
NetworkQueryHostIp nqhip = NetworkQueryHostIp.create(urls);
NetworkQueryHostIp nqhip =
makeNetworkQueryHostIp(
Map.of(
"a", Result.success(new HostIp("1")),
"b", Result.success(new HostIp("2")),
"c", Result.success(new HostIp("2")),
"d", Result.success(new HostIp("4"))));
Optional<HostIp> host = nqhip.queryNetworkHosts().conclusiveHostIp();
assertFalse(host.isPresent());
assertEquals(Optional.of(new HostIp("2")), host);
}

private static URL makeUrl(int status, String body) throws IOException {
HttpURLConnection conn = mock(HttpURLConnection.class);
doReturn(status).when(conn).getResponseCode();
doReturn(new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8)))
.when(conn)
.getInputStream();
URL url = mock(URL.class);
doReturn(conn).when(url).openConnection();
doReturn("https://mock.url/?result=%s".formatted(body)).when(url).toString();
return url;
NetworkQueryHostIp makeNetworkQueryHostIp(Map<String, Result<HostIp, IOException>> responses) {
NetworkQueryHostIp nqhip = spy(NetworkQueryHostIp.class);
doReturn(new ArrayList<String>(responses.keySet())).when(nqhip).hosts();
for (var entry : responses.entrySet()) {
doReturn(entry.getValue()).when(nqhip).query(Mockito.eq(entry.getKey()));
}
return nqhip;
}
}

0 comments on commit 4498e16

Please sign in to comment.