Refactor FCP dialog
[jFCPlib.git] / src / main / java / net / pterodactylus / fcp / quelaton / ClientHelloImpl.java
1 package net.pterodactylus.fcp.quelaton;
2
3 import java.io.IOException;
4 import java.util.concurrent.ExecutionException;
5 import java.util.concurrent.ExecutorService;
6 import java.util.concurrent.atomic.AtomicReference;
7
8 import net.pterodactylus.fcp.ClientHello;
9 import net.pterodactylus.fcp.FcpConnection;
10 import net.pterodactylus.fcp.NodeHello;
11
12 import com.google.common.util.concurrent.ListenableFuture;
13 import com.google.common.util.concurrent.ListeningExecutorService;
14 import com.google.common.util.concurrent.MoreExecutors;
15
16 /**
17  * Internal <code>ClientHello</code> implementation based on {@link FcpDialog}.
18  *
19  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
20  */
21 public class ClientHelloImpl {
22
23         private final ListeningExecutorService threadPool;
24         private final String hostname;
25         private final int port;
26         private final AtomicReference<String> clientName = new AtomicReference<>();
27
28         public ClientHelloImpl(ExecutorService threadPool, String hostname, int port) {
29                 this.threadPool = MoreExecutors.listeningDecorator(threadPool);
30                 this.hostname = hostname;
31                 this.port = port;
32         }
33
34         public Executable<FcpConnection> withName(String name) {
35                 clientName.set(name);
36                 return this::execute;
37         }
38
39         private ListenableFuture<FcpConnection> execute() {
40                 return threadPool.submit(this::establishConnection);
41         }
42
43         private FcpConnection establishConnection() throws IOException {
44                 FcpConnection connection = new FcpConnection(hostname, port);
45                 connection.connect();
46                 ClientHello clientHello = new ClientHello(clientName.get(), "2.0");
47                 try (ClientHelloDialog clientHelloDialog = new ClientHelloDialog(connection)) {
48                         if (clientHelloDialog.send(clientHello).get()) {
49                                 return connection;
50                         }
51                 } catch (InterruptedException | ExecutionException e) {
52                         connection.close();
53                         throw new IOException(String.format("Could not connect to %s:%d.", hostname, port), e);
54                 }
55                 connection.close();
56                 throw new IOException(String.format("Could not connect to %s:%d.", hostname, port));
57         }
58
59         private class ClientHelloDialog extends FcpDialog<Boolean> {
60
61                 public ClientHelloDialog(FcpConnection connection) {
62                         super(ClientHelloImpl.this.threadPool, connection, false);
63                 }
64
65                 @Override
66                 protected void consumeNodeHello(NodeHello nodeHello) {
67                         setResult(true);
68                 }
69
70         }
71
72 }