From 9af5bd326500773d89ce30311af5e3cac2a9b3f5 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Tue, 29 Sep 2026 06:39:04 +0000
Subject: [PATCH] [#1112] Listen on the configured listen-address in the HTTP connection handler and the JMX RMI connector (#1113)

---
 opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java |   73 ++++++++++++++++++++++++------------
 1 files changed, 48 insertions(+), 25 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java
index 9f94105..a3a61d9 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java
@@ -30,7 +30,6 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -133,8 +132,8 @@
   /** Indicates whether this connection handler is enabled. */
   private boolean enabled;
 
-  /** The set of listeners for this connection handler. */
-  private final List<HostPort> listeners = new LinkedList<>();
+  /** The addresses and the port the HTTP server listens on, or starts with next. */
+  private volatile List<HostPort> listeners = Collections.emptyList();
 
   /** The HTTP server embedded in OpenDJ. */
   private HttpServer httpServer;
@@ -448,11 +447,7 @@
       friendlyName = config.name();
     }
 
-    int listenPort = config.getListenPort();
-    for (InetAddress a : config.getListenAddress())
-    {
-      listeners.add(new HostPort(a.getHostAddress(), listenPort));
-    }
+    listeners = toListeners(config);
 
     handlerName = getHandlerName(config);
 
@@ -770,7 +765,17 @@
     this.httpServer = createHttpServer();
     this.httpServer.getServerConfiguration().addHttpHandler(newGrizzlyHttpHandler(new RootHttpApplication()));
     logger.trace("Starting HTTP server...");
-    this.httpServer.start();
+    try
+    {
+      this.httpServer.start();
+    }
+    catch (IOException | RuntimeException e)
+    {
+      // HttpServer.start() stops at the first listener that cannot bind and leaves the listeners started before it
+      // bound: release their addresses, since the caller only forgets about the server.
+      this.httpServer.shutdownNow();
+      throw e;
+    }
     logger.trace("HTTP server started");
     logger.info(NOTE_CONNHANDLER_STARTED_LISTENING, handlerName);
   }
@@ -790,13 +795,41 @@
       setHttpStatsProbe(server);
     }
 
-    // Configure the network listener
-    final NetworkListener listener = new NetworkListener(
-        "OpenDJ-HTTP", NetworkListener.DEFAULT_NETWORK_HOST, initConfig.getListenPort());
-    server.addListener(listener);
+    // Configure one network listener per listen address, and report them: a configuration change can replace
+    // initConfig after the initialization. HttpServer keys its listeners by name, and each listener owns its
+    // transport, so neither can be shared.
+    listeners = toListeners(initConfig);
+    final int numRequestHandlers = getNumRequestHandlers(currentConfig.getNumRequestHandlers(), friendlyName);
+    for (InetAddress address : initConfig.getListenAddress())
+    {
+      final String host = address.getHostAddress();
+      final NetworkListener listener = new NetworkListener("OpenDJ-HTTP " + host, host, initConfig.getListenPort());
+      server.addListener(listener);
+      configureTransport(listener.getTransport(), numRequestHandlers);
 
-    // Configure the network transport
-    final TCPNIOTransport transport = listener.getTransport();
+      // Configure SSL
+      if (sslEngineConfigurator != null)
+      {
+        listener.setSecure(true);
+        listener.setSSLEngineConfig(sslEngineConfigurator);
+      }
+    }
+
+    return server;
+  }
+
+  private static List<HostPort> toListeners(HTTPConnectionHandlerCfg config)
+  {
+    final List<HostPort> hostPorts = new ArrayList<>();
+    for (InetAddress address : config.getListenAddress())
+    {
+      hostPorts.add(new HostPort(address.getHostAddress(), config.getListenPort()));
+    }
+    return Collections.unmodifiableList(hostPorts);
+  }
+
+  private void configureTransport(TCPNIOTransport transport, int numRequestHandlers)
+  {
     transport.setReuseAddress(currentConfig.isAllowTCPReuseAddress());
     transport.setKeepAlive(currentConfig.isUseTCPKeepAlive());
     transport.setTcpNoDelay(currentConfig.isUseTCPNoDelay());
@@ -807,18 +840,8 @@
     transport.setWriteBufferSize(bufferSize);
     transport.setIOStrategy(SameThreadIOStrategy.getInstance());
 
-    final int numRequestHandlers = getNumRequestHandlers(currentConfig.getNumRequestHandlers(), friendlyName);
     transport.setSelectorRunnersCount(numRequestHandlers);
     transport.setServerConnectionBackLog(currentConfig.getAcceptBacklog());
-
-    // Configure SSL
-    if (sslEngineConfigurator != null)
-    {
-      listener.setSecure(true);
-      listener.setSSLEngineConfig(sslEngineConfigurator);
-    }
-
-    return server;
   }
 
   private void setHttpStatsProbe(HttpServer server)

--
Gitblit v1.10.0