}
@Override
+ public GetNodeCommand getNode() {
+ return new GetNodeCommandImpl(threadPool, this::connect);
+ }
+
+ @Override
public GenerateKeypairCommand generateKeypair() {
return new GenerateKeypairCommandImpl(threadPool, this::connect);
}
*/
public interface FcpClient {
+ GetNodeCommand getNode();
GenerateKeypairCommand generateKeypair();
ClientGetCommand clientGet();
ClientPutCommand clientPut();
--- /dev/null
+package net.pterodactylus.fcp.quelaton;
+
+import net.pterodactylus.fcp.NodeData;
+
+/**
+ * Returns information about the FCP server itself.
+ *
+ * @author <a href="mailto:bombe@freenetproject.org">David ‘Bombe’ Roden</a>
+ */
+public interface GetNodeCommand extends Executable<NodeData> {
+
+}
--- /dev/null
+package net.pterodactylus.fcp.quelaton;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicReference;
+
+import net.pterodactylus.fcp.GetNode;
+import net.pterodactylus.fcp.NodeData;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+/**
+ * Default {@link GetNodeCommandImpl} implementation based on {@link FcpReplySequence}.
+ *
+ * @author <a href="mailto:bombe@freenetproject.org">David ‘Bombe’ Roden</a>
+ */
+public class GetNodeCommandImpl implements GetNodeCommand {
+
+ private final ListeningExecutorService threadPool;
+ private final ConnectionSupplier connectionSupplier;
+
+ public GetNodeCommandImpl(ExecutorService threadPool, ConnectionSupplier connectionSupplier) {
+ this.threadPool = MoreExecutors.listeningDecorator(threadPool);
+ this.connectionSupplier = connectionSupplier;
+ }
+
+ @Override
+ public ListenableFuture<NodeData> execute() {
+ GetNode getNode = new GetNode(new RandomIdentifierGenerator().generate(), false, false, false);
+ return threadPool.submit(() -> new GetNodeReplySequence().send(getNode).get());
+ }
+
+ private class GetNodeReplySequence extends FcpReplySequence<NodeData> {
+
+ private final AtomicReference<NodeData> nodeData = new AtomicReference<>();
+
+ public GetNodeReplySequence() throws IOException {
+ super(threadPool, connectionSupplier.get());
+ }
+
+ @Override
+ protected boolean isFinished() {
+ return nodeData.get() != null;
+ }
+
+ @Override
+ protected NodeData getResult() {
+ return nodeData.get();
+ }
+
+ @Override
+ protected void consumeNodeData(NodeData nodeData) {
+ this.nodeData.set(nodeData);
+ }
+
+ }
+
+}
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
import java.io.ByteArrayInputStream;
import java.io.File;
import net.pterodactylus.fcp.FcpKeyPair;
import net.pterodactylus.fcp.Key;
+import net.pterodactylus.fcp.NodeData;
import net.pterodactylus.fcp.Peer;
import net.pterodactylus.fcp.Priority;
import net.pterodactylus.fcp.fake.FakeTcpServer;
containsInAnyOrder("bar1", "bar2"));
}
+ @Test
+ public void defaultFcpClientCanGetNodeInformation() throws InterruptedException, ExecutionException, IOException {
+ Future<NodeData> nodeData = fcpClient.getNode().execute();
+ connectNode();
+ List<String> lines = fcpServer.collectUntil(is("EndMessage"));
+ String identifier = extractIdentifier(lines);
+ assertThat(lines, matchesFcpMessage(
+ "GetNode",
+ "Identifier=" + identifier,
+ "GiveOpennetRef=false",
+ "WithPrivate=false",
+ "WithVolatile=false",
+ "EndMessage"
+ ));
+ fcpServer.writeLine(
+ "NodeData",
+ "Identifier=" + identifier,
+ "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(nodeData.get(), notNullValue());
+ }
+
}