1 package net.pterodactylus.fcp.quelaton;
3 import java.io.IOException;
4 import java.util.concurrent.ExecutionException;
5 import java.util.concurrent.ExecutorService;
6 import java.util.concurrent.atomic.AtomicBoolean;
7 import java.util.concurrent.atomic.AtomicReference;
9 import net.pterodactylus.fcp.ClientHello;
10 import net.pterodactylus.fcp.CloseConnectionDuplicateClientName;
11 import net.pterodactylus.fcp.FcpConnection;
12 import net.pterodactylus.fcp.NodeHello;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.common.util.concurrent.ListeningExecutorService;
16 import com.google.common.util.concurrent.MoreExecutors;
19 * Internal <code>ClientHello</code> implementation based on {@link FcpReplySequence}.
21 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
23 public class ClientHelloImpl {
25 private final ListeningExecutorService threadPool;
26 private final String hostname;
27 private final int port;
28 private final AtomicReference<String> clientName = new AtomicReference<>();
30 public ClientHelloImpl(ExecutorService threadPool, String hostname, int port) {
31 this.threadPool = MoreExecutors.listeningDecorator(threadPool);
32 this.hostname = hostname;
36 public Executable<FcpConnection> withName(String name) {
41 private ListenableFuture<FcpConnection> execute() {
42 return threadPool.submit(() -> establishConnection());
45 private FcpConnection establishConnection() throws IOException {
46 FcpConnection connection = new FcpConnection(hostname, port);
48 ClientHelloReplySequence nodeHelloSequence = new ClientHelloReplySequence(connection);
49 ClientHello clientHello = new ClientHello(clientName.get(), "2.0");
51 if (nodeHelloSequence.send(clientHello).get()) {
54 } catch (InterruptedException | ExecutionException e) {
56 throw new IOException(String.format("Could not connect to %s:%d.", hostname, port), e);
59 throw new IOException(String.format("Could not connect to %s:%d.", hostname, port));
62 private class ClientHelloReplySequence extends FcpReplySequence<Boolean> {
64 private final AtomicReference<NodeHello> receivedNodeHello = new AtomicReference<>();
65 private final AtomicBoolean receivedClosed = new AtomicBoolean();
67 public ClientHelloReplySequence(FcpConnection connection) {
68 super(ClientHelloImpl.this.threadPool, connection);
72 protected boolean isFinished() {
73 return receivedNodeHello.get() != null || receivedClosed.get();
77 protected Boolean getResult() {
78 return receivedNodeHello.get() != null;
82 protected void consumeNodeHello(NodeHello nodeHello) {
83 receivedNodeHello.set(nodeHello);
87 protected void consumeCloseConnectionDuplicateClientName(
88 CloseConnectionDuplicateClientName closeConnectionDuplicateClientName) {
89 receivedClosed.set(true);