]> nmode's Git Repositories - signal-cli/blobdiff - src/main/java/org/asamk/signal/http/HttpServerHandler.java
Update gradle
[signal-cli] / src / main / java / org / asamk / signal / http / HttpServerHandler.java
index b888464e1bd624267c372e70d42164ec12b34509..542d928ba542ef28df023c8f8d9fa95655c175f5 100644 (file)
@@ -24,9 +24,9 @@ import java.util.Map;
 import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-public class HttpServerHandler {
+public class HttpServerHandler implements AutoCloseable {
 
-    private final static Logger logger = LoggerFactory.getLogger(HttpServerHandler.class);
+    private static final Logger logger = LoggerFactory.getLogger(HttpServerHandler.class);
 
     private final ObjectMapper objectMapper = Util.createJsonObjectMapper();
 
@@ -35,6 +35,8 @@ public class HttpServerHandler {
     private final SignalJsonRpcCommandHandler commandHandler;
     private final MultiAccountManager c;
     private final Manager m;
+    private HttpServer server;
+    private final AtomicBoolean shutdown = new AtomicBoolean(false);
 
     public HttpServerHandler(final InetSocketAddress address, final Manager m) {
         this.address = address;
@@ -51,9 +53,12 @@ public class HttpServerHandler {
     }
 
     public void init() throws IOException {
-        logger.info("Starting server on " + address.toString());
+        if (server != null) {
+            throw new AssertionError("HttpServerHandler already initialized");
+        }
+        logger.debug("Starting HTTP server on {}", address);
 
-        final var server = HttpServer.create(address, 0);
+        server = HttpServer.create(address, 0);
         server.setExecutor(Executors.newCachedThreadPool());
 
         server.createContext("/api/v1/rpc", this::handleRpcEndpoint);
@@ -61,6 +66,21 @@ public class HttpServerHandler {
         server.createContext("/api/v1/check", this::handleCheckEndpoint);
 
         server.start();
+        logger.info("Started HTTP server on {}", address);
+    }
+
+    @Override
+    public void close() {
+        if (server != null) {
+            shutdown.set(true);
+            synchronized (this) {
+                this.notifyAll();
+            }
+            // Increase this delay when https://bugs.openjdk.org/browse/JDK-8304065 is fixed
+            server.stop(2);
+            server = null;
+            shutdown.set(false);
+        }
     }
 
     private void sendResponse(int status, Object response, HttpExchange httpExchange) throws IOException {
@@ -136,7 +156,7 @@ public class HttpServerHandler {
         }
 
         try {
-            final var queryString = httpExchange.getRequestURI().getQuery();
+            final var queryString = httpExchange.getRequestURI().getRawQuery();
             final var query = queryString == null ? Map.<String, String>of() : Util.getQueryMap(queryString);
 
             List<Manager> managers = getManagerFromQuery(query);
@@ -153,7 +173,7 @@ public class HttpServerHandler {
             final var handlers = subscribeReceiveHandlers(managers, sender, () -> {
                 shouldStop.set(true);
                 synchronized (this) {
-                    this.notify();
+                    this.notifyAll();
                 }
             });
 
@@ -162,7 +182,7 @@ public class HttpServerHandler {
                     synchronized (this) {
                         wait(15_000);
                     }
-                    if (shouldStop.get()) {
+                    if (shouldStop.get() || shutdown.get()) {
                         break;
                     }
 
@@ -216,11 +236,13 @@ public class HttpServerHandler {
                 return List.of(manager);
             }
         }
-        return List.of();
+        throw new AssertionError("Unreachable state");
     }
 
     private List<Pair<Manager, Manager.ReceiveMessageHandler>> subscribeReceiveHandlers(
-            final List<Manager> managers, final ServerSentEventSender sender, Callable unsubscribe
+            final List<Manager> managers,
+            final ServerSentEventSender sender,
+            Callable unsubscribe
     ) {
         return managers.stream().map(m1 -> {
             final var receiveMessageHandler = new JsonReceiveMessageHandler(m1, s -> {