X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Ffcp%2Fquelaton%2FFcpReplySequence.java;h=9b44b9a4e47283ea9f12be4952463b1e1a2c402f;hb=ff2e4b93bfb1030fd11ec295f4ae6e9bd29b6966;hp=106bd8abceec60bd1054615215f0f9449247a930;hpb=14d38c217ac5e222e8d0d26eb4264fd69f9395d6;p=jFCPlib.git diff --git a/src/main/java/net/pterodactylus/fcp/quelaton/FcpReplySequence.java b/src/main/java/net/pterodactylus/fcp/quelaton/FcpReplySequence.java index 106bd8a..9b44b9a 100644 --- a/src/main/java/net/pterodactylus/fcp/quelaton/FcpReplySequence.java +++ b/src/main/java/net/pterodactylus/fcp/quelaton/FcpReplySequence.java @@ -1,12 +1,17 @@ package net.pterodactylus.fcp.quelaton; import java.io.IOException; +import java.util.Objects; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import net.pterodactylus.fcp.AllData; +import net.pterodactylus.fcp.BaseMessage; import net.pterodactylus.fcp.CloseConnectionDuplicateClientName; import net.pterodactylus.fcp.ConfigData; import net.pterodactylus.fcp.DataFound; @@ -62,30 +67,42 @@ public abstract class FcpReplySequence implements AutoCloseable, FcpListener private final ListeningExecutorService executorService; private final FcpConnection fcpConnection; private final Queue messages = new ConcurrentLinkedQueue<>(); + private final AtomicReference identifier = new AtomicReference<>(); + private final AtomicBoolean connectionClosed = new AtomicBoolean(); + private final AtomicReference connectionFailureReason = new AtomicReference<>(); public FcpReplySequence(ExecutorService executorService, FcpConnection fcpConnection) { this.executorService = MoreExecutors.listeningDecorator(executorService); this.fcpConnection = fcpConnection; } + protected void setIdentifier(String identifier) { + this.identifier.set(identifier); + } + protected abstract boolean isFinished(); public ListenableFuture send(FcpMessage fcpMessage) throws IOException { + setIdentifier(fcpMessage.getField("Identifier")); fcpConnection.addFcpListener(this); messages.add(fcpMessage); return executorService.submit(() -> { synchronized (syncObject) { - while (!isFinished() || !messages.isEmpty()) { + while (!connectionClosed.get() && (!isFinished() || !messages.isEmpty())) { while (messages.peek() != null) { FcpMessage message = messages.poll(); fcpConnection.sendMessage(message); } - if (isFinished()) { + if (isFinished() || connectionClosed.get()) { continue; } syncObject.wait(); } } + Throwable throwable = connectionFailureReason.get(); + if (throwable != null) { + throw new ExecutionException(throwable); + } return getResult(); }); } @@ -110,7 +127,18 @@ public abstract class FcpReplySequence implements AutoCloseable, FcpListener fcpConnection.removeFcpListener(this); } - private void consume(Consumer consumer, M message) { + private void consume(Consumer consumer, M message) { + consume(consumer, message, "Identifier"); + } + + private void consume(Consumer consumer, M message, + String identifier) { + if (Objects.equals(message.getField(identifier), this.identifier.get())) { + consumeAlways(consumer, message); + } + } + + private void consumeAlways(Consumer consumer, M message) { consumer.accept(message); notifySyncObject(); } @@ -121,7 +149,8 @@ public abstract class FcpReplySequence implements AutoCloseable, FcpListener } private void consumeClose(Throwable throwable) { - consumeConnectionClosed(throwable); + connectionFailureReason.set(throwable); + connectionClosed.set(true); notifySyncObject(); } @@ -135,11 +164,11 @@ public abstract class FcpReplySequence implements AutoCloseable, FcpListener @Override public final void receivedCloseConnectionDuplicateClientName(FcpConnection fcpConnection, CloseConnectionDuplicateClientName closeConnectionDuplicateClientName) { - consume(this::consumeCloseConnectionDuplicateClientName, closeConnectionDuplicateClientName); + connectionFailureReason.set(new IOException("duplicate client name")); + connectionClosed.set(true); + notifySyncObject(); } - protected void consumeCloseConnectionDuplicateClientName(CloseConnectionDuplicateClientName closeConnectionDuplicateClientName) { } - @Override public final void receivedSSKKeypair(FcpConnection fcpConnection, SSKKeypair sskKeypair) { consume(this::consumeSSKKeypair, sskKeypair); @@ -191,14 +220,14 @@ public abstract class FcpReplySequence implements AutoCloseable, FcpListener @Override public final void receivedTestDDAReply(FcpConnection fcpConnection, TestDDAReply testDDAReply) { - consume(this::consumeTestDDAReply, testDDAReply); + consume(this::consumeTestDDAReply, testDDAReply, "Directory"); } protected void consumeTestDDAReply(TestDDAReply testDDAReply) { } @Override public final void receivedTestDDAComplete(FcpConnection fcpConnection, TestDDAComplete testDDAComplete) { - consume(this::consumeTestDDAComplete, testDDAComplete); + consume(this::consumeTestDDAComplete, testDDAComplete, "Directory"); } protected void consumeTestDDAComplete(TestDDAComplete testDDAComplete) { } @@ -401,6 +430,4 @@ public abstract class FcpReplySequence implements AutoCloseable, FcpListener consumeClose(throwable); } - protected void consumeConnectionClosed(Throwable throwable) { } - }