X-Git-Url: https://git.nmode.ca/signal-cli/blobdiff_plain/62dd2ee49ebcc182fb3892648c3f3f3840d38652..fc8b6d0fcbedd6a4c9ae394a0640e79690e28337:/src/main/java/org/asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java diff --git a/src/main/java/org/asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java b/src/main/java/org/asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java index d2debfe0..cb87687e 100644 --- a/src/main/java/org/asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java +++ b/src/main/java/org/asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java @@ -6,19 +6,22 @@ import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ContainerNode; +import com.fasterxml.jackson.databind.node.ObjectNode; -import org.asamk.signal.JsonReceiveMessageHandler; -import org.asamk.signal.JsonWriter; import org.asamk.signal.commands.Command; import org.asamk.signal.commands.Commands; import org.asamk.signal.commands.JsonRpcMultiCommand; +import org.asamk.signal.commands.JsonRpcRegistrationCommand; import org.asamk.signal.commands.JsonRpcSingleCommand; -import org.asamk.signal.commands.SignalCreator; import org.asamk.signal.commands.exceptions.CommandException; import org.asamk.signal.commands.exceptions.IOErrorException; import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException; import org.asamk.signal.commands.exceptions.UserErrorException; +import org.asamk.signal.json.JsonReceiveMessageHandler; import org.asamk.signal.manager.Manager; +import org.asamk.signal.manager.MultiAccountManager; +import org.asamk.signal.manager.RegistrationManager; +import org.asamk.signal.output.JsonWriter; import org.asamk.signal.util.Util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,7 +45,7 @@ public class SignalJsonRpcDispatcherHandler { private final JsonRpcReader jsonRpcReader; private final boolean noReceiveOnStart; - private SignalCreator c; + private MultiAccountManager c; private final Map receiveHandlers = new HashMap<>(); private Manager m; @@ -56,11 +59,13 @@ public class SignalJsonRpcDispatcherHandler { this.jsonRpcReader = new JsonRpcReader(jsonRpcSender, lineSupplier); } - public void handleConnection(final SignalCreator c) { + public void handleConnection(final MultiAccountManager c) { this.c = c; if (!noReceiveOnStart) { c.getAccountNumbers().stream().map(c::getManager).filter(Objects::nonNull).forEach(this::subscribeReceive); + c.addOnManagerAddedHandler(this::subscribeReceive); + c.addOnManagerRemovedHandler(this::unsubscribeReceive); } handleConnection(); @@ -73,6 +78,9 @@ public class SignalJsonRpcDispatcherHandler { subscribeReceive(m); } + final var currentThread = Thread.currentThread(); + m.addClosedListener(currentThread::interrupt); + handleConnection(); } @@ -119,20 +127,34 @@ public class SignalJsonRpcDispatcherHandler { final ObjectMapper objectMapper, final String method, ContainerNode params ) throws JsonRpcException { var command = getCommand(method); - // TODO implement register, verify, link - if (c != null && command instanceof JsonRpcMultiCommand jsonRpcCommand) { - return runCommand(objectMapper, params, new MultiCommandRunnerImpl<>(c, jsonRpcCommand)); + if (c != null) { + if (command instanceof JsonRpcMultiCommand jsonRpcCommand) { + return runCommand(objectMapper, params, new MultiCommandRunnerImpl<>(c, jsonRpcCommand)); + } + if (command instanceof JsonRpcRegistrationCommand jsonRpcCommand) { + try (var manager = getRegistrationManagerFromParams(params)) { + if (manager != null) { + return runCommand(objectMapper, + params, + new RegistrationCommandRunnerImpl<>(manager, c, jsonRpcCommand)); + } else { + throw new JsonRpcException(new JsonRpcResponse.Error(JsonRpcResponse.Error.INVALID_PARAMS, + "Method requires valid account parameter", + null)); + } + } catch (IOException e) { + logger.warn("Failed to close registration manager", e); + } + } } if (command instanceof JsonRpcSingleCommand jsonRpcCommand) { if (m != null) { return runCommand(objectMapper, params, new CommandRunnerImpl<>(m, jsonRpcCommand)); } - if (params.has("account")) { - Manager manager = c.getManager(params.get("account").asText()); - if (manager != null) { - return runCommand(objectMapper, params, new CommandRunnerImpl<>(manager, jsonRpcCommand)); - } + final var manager = getManagerFromParams(params); + if (manager != null) { + return runCommand(objectMapper, params, new CommandRunnerImpl<>(manager, jsonRpcCommand)); } else { throw new JsonRpcException(new JsonRpcResponse.Error(JsonRpcResponse.Error.INVALID_PARAMS, "Method requires valid account parameter", @@ -145,6 +167,29 @@ public class SignalJsonRpcDispatcherHandler { null)); } + private Manager getManagerFromParams(final ContainerNode params) { + if (params != null && params.has("account")) { + final var manager = c.getManager(params.get("account").asText()); + ((ObjectNode) params).remove("account"); + return manager; + } + return null; + } + + private RegistrationManager getRegistrationManagerFromParams(final ContainerNode params) { + if (params != null && params.has("account")) { + try { + final var registrationManager = c.getNewRegistrationManager(params.get("account").asText()); + ((ObjectNode) params).remove("account"); + return registrationManager; + } catch (IOException | IllegalStateException e) { + logger.warn("Failed to load registration manager", e); + return null; + } + } + return null; + } + private Command getCommand(final String method) { if ("subscribeReceive".equals(method)) { return new SubscribeReceiveCommand(); @@ -168,8 +213,23 @@ public class SignalJsonRpcDispatcherHandler { } } + private record RegistrationCommandRunnerImpl( + RegistrationManager m, MultiAccountManager c, JsonRpcRegistrationCommand command + ) implements CommandRunner { + + @Override + public void handleCommand(final T request, final JsonWriter jsonWriter) throws CommandException { + command.handleCommand(request, m, jsonWriter); + } + + @Override + public TypeReference getRequestType() { + return command.getRequestType(); + } + } + private record MultiCommandRunnerImpl( - SignalCreator c, JsonRpcMultiCommand command + MultiAccountManager c, JsonRpcMultiCommand command ) implements CommandRunner { @Override