From fc1c3f3719425dfafb42fedef9ecad05783dd32c Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Sat, 11 Jul 2015 04:25:48 +0200 Subject: [PATCH] Add ListPeer command --- .../fcp/quelaton/DefaultFcpClient.java | 5 + .../net/pterodactylus/fcp/quelaton/FcpClient.java | 1 + .../fcp/quelaton/ListPeerCommand.java | 18 ++++ .../fcp/quelaton/ListPeerCommandImpl.java | 93 ++++++++++++++++++ .../fcp/quelaton/DefaultFcpClientTest.java | 106 +++++++++++++++++++++ 5 files changed, 223 insertions(+) create mode 100644 src/main/java/net/pterodactylus/fcp/quelaton/ListPeerCommand.java create mode 100644 src/main/java/net/pterodactylus/fcp/quelaton/ListPeerCommandImpl.java diff --git a/src/main/java/net/pterodactylus/fcp/quelaton/DefaultFcpClient.java b/src/main/java/net/pterodactylus/fcp/quelaton/DefaultFcpClient.java index d40659a..6cefb46 100644 --- a/src/main/java/net/pterodactylus/fcp/quelaton/DefaultFcpClient.java +++ b/src/main/java/net/pterodactylus/fcp/quelaton/DefaultFcpClient.java @@ -70,6 +70,11 @@ public class DefaultFcpClient implements FcpClient { } @Override + public ListPeerCommand listPeer() { + return new ListPeerCommandImpl(threadPool, this::connect); + } + + @Override public ListPeersCommand listPeers() { return new ListPeersCommandImpl(threadPool, this::connect); } diff --git a/src/main/java/net/pterodactylus/fcp/quelaton/FcpClient.java b/src/main/java/net/pterodactylus/fcp/quelaton/FcpClient.java index 5cbec0f..c4c6d51 100644 --- a/src/main/java/net/pterodactylus/fcp/quelaton/FcpClient.java +++ b/src/main/java/net/pterodactylus/fcp/quelaton/FcpClient.java @@ -12,6 +12,7 @@ public interface FcpClient { ClientGetCommand clientGet(); ClientPutCommand clientPut(); + ListPeerCommand listPeer(); ListPeersCommand listPeers(); } diff --git a/src/main/java/net/pterodactylus/fcp/quelaton/ListPeerCommand.java b/src/main/java/net/pterodactylus/fcp/quelaton/ListPeerCommand.java new file mode 100644 index 0000000..e2ac9df --- /dev/null +++ b/src/main/java/net/pterodactylus/fcp/quelaton/ListPeerCommand.java @@ -0,0 +1,18 @@ +package net.pterodactylus.fcp.quelaton; + +import java.util.Optional; + +import net.pterodactylus.fcp.Peer; + +/** + * Lists a single peer by its name (darknet only), identity, or host name/IP address and port number. + * + * @author David ‘Bombe’ Roden + */ +public interface ListPeerCommand { + + Executable> byName(String name); + Executable> byIdentity(String identity); + Executable> byHostAndPort(String host, int port); + +} diff --git a/src/main/java/net/pterodactylus/fcp/quelaton/ListPeerCommandImpl.java b/src/main/java/net/pterodactylus/fcp/quelaton/ListPeerCommandImpl.java new file mode 100644 index 0000000..dd91133 --- /dev/null +++ b/src/main/java/net/pterodactylus/fcp/quelaton/ListPeerCommandImpl.java @@ -0,0 +1,93 @@ +package net.pterodactylus.fcp.quelaton; + +import java.io.IOException; +import java.util.Optional; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +import net.pterodactylus.fcp.ListPeer; +import net.pterodactylus.fcp.Peer; +import net.pterodactylus.fcp.UnknownNodeIdentifier; + +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; + +/** + * Default {@link ListPeerCommand} implementation based on {@link FcpReplySequence}. + * + * @author David ‘Bombe’ Roden + */ +public class ListPeerCommandImpl implements ListPeerCommand { + + private final ListeningExecutorService threadPool; + private final ConnectionSupplier connectionSupplier; + private final AtomicReference nodeIdentifier = new AtomicReference<>(); + + public ListPeerCommandImpl(ListeningExecutorService threadPool, ConnectionSupplier connectionSupplier) { + this.threadPool = threadPool; + this.connectionSupplier = connectionSupplier; + } + + @Override + public Executable> byName(String name) { + nodeIdentifier.set(name); + return this::execute; + } + + @Override + public Executable> byIdentity(String identity) { + nodeIdentifier.set(identity); + return this::execute; + } + + @Override + public Executable> byHostAndPort(String host, int port) { + nodeIdentifier.set(String.format("%s:%d", host, port)); + return this::execute; + } + + private ListenableFuture> execute() { + return threadPool.submit(this::executeSequence); + } + + private Optional executeSequence() throws IOException, ExecutionException, InterruptedException { + ListPeer listPeer = new ListPeer(new RandomIdentifierGenerator().generate(), nodeIdentifier.get()); + try (ListPeerSequence listPeerSequence = new ListPeerSequence()) { + return Optional.ofNullable(listPeerSequence.send(listPeer).get()); + } + } + + private class ListPeerSequence extends FcpReplySequence { + + private final AtomicBoolean finished = new AtomicBoolean(); + private final AtomicReference peer = new AtomicReference<>(); + + public ListPeerSequence() throws IOException { + super(threadPool, connectionSupplier.get()); + } + + @Override + protected boolean isFinished() { + return finished.get(); + } + + @Override + protected Peer getResult() { + return peer.get(); + } + + @Override + protected void consumePeer(Peer peer) { + this.peer.set(peer); + finished.set(true); + } + + @Override + protected void consumeUnknownNodeIdentifier(UnknownNodeIdentifier unknownNodeIdentifier) { + finished.set(true); + } + + } + +} diff --git a/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java b/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java index bfb2b78..9108c17 100644 --- a/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java +++ b/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java @@ -892,4 +892,110 @@ public class DefaultFcpClientTest { assertThat(nodeData.get().getVolatile("freeJavaMemory").toString(), is("205706528")); } + @Test + public void defaultFcpClientCanListSinglePeerByIdentity() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.listPeer().byIdentity("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ListPeer", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "EndMessage" + )); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id1", + "opennet=false", + "ark.pubURI=SSK@3YEf.../ark", + "ark.number=78", + "auth.negTypes=2", + "version=Fred,0.7,1.0,1466", + "lastGoodVersion=Fred,0.7,1.0,1466", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity().toString(), is("id1")); + } + + @Test + public void defaultFcpClientCanListSinglePeerByHostAndPort() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.listPeer().byHostAndPort("host.free.net", 12345).execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ListPeer", + "Identifier=" + identifier, + "NodeIdentifier=host.free.net:12345", + "EndMessage" + )); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id1", + "opennet=false", + "ark.pubURI=SSK@3YEf.../ark", + "ark.number=78", + "auth.negTypes=2", + "version=Fred,0.7,1.0,1466", + "lastGoodVersion=Fred,0.7,1.0,1466", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity().toString(), is("id1")); + } + + @Test + public void defaultFcpClientCanListSinglePeerByName() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.listPeer().byName("FriendNode").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ListPeer", + "Identifier=" + identifier, + "NodeIdentifier=FriendNode", + "EndMessage" + )); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id1", + "opennet=false", + "ark.pubURI=SSK@3YEf.../ark", + "ark.number=78", + "auth.negTypes=2", + "version=Fred,0.7,1.0,1466", + "lastGoodVersion=Fred,0.7,1.0,1466", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity().toString(), is("id1")); + } + + @Test + public void defaultFcpClientRecognizesUnknownNodeIdentifiers() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.listPeer().byIdentity("id2").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ListPeer", + "Identifier=" + identifier, + "NodeIdentifier=id2", + "EndMessage" + )); + fcpServer.writeLine( + "UnknownNodeIdentifier", + "Identifier=" + identifier, + "NodeIdentifier=id2", + "EndMessage" + ); + assertThat(peer.get().isPresent(), is(false)); + } + } -- 2.7.4