Build: #3206 was successful
Job: Workflow was successful
Code commits
Openfire (master)
-
Guus der Kinderen 0586d226baeac8960c24d1087768d783dbb5fbe8
OF-3176: start DirectTLS and enable autoRead before business logic handler sees channelActive
In both NettyServerInitializer and NettySessionInitializer, the handler responsible for starting DirectTLS and enabling autoRead was appended to the end of the pipeline via a trailing addLast() call. Since channelActive propagates head-to-tail, this meant the business logic handler received channelActive before TLS was initiated and before autoRead was enabled.
Move the tlsAndAutoReadHandler to immediately before businessLogicHandler in both pipelines, ensuring TLS startup and autoRead are sequenced correctly relative to business logic processing.
Also give businessLogicHandler an explicit pipeline name for clarity.- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettySessionInitializer.java (version 0586d226baeac8960c24d1087768d783dbb5fbe8)
- xmppserver/src/main/java/org/jivesoftware/openfire/spi/NettyServerInitializer.java (version 0586d226baeac8960c24d1087768d783dbb5fbe8)
-
Guus der Kinderen 609c03c8f7bd53a7a17844e6f2a1f53cefadff89
OF-3176: Preserve backward compatibility for NettyChannelHandlerFactory per review feedback
Keep the original addNewHandlerTo(ChannelPipeline) method and add an executor-aware overload as default, avoiding breaking existing plugin implementations.- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettyChannelHandlerFactory.java (version 609c03c8f7bd53a7a17844e6f2a1f53cefadff89)
-
Guus der Kinderen dab901d1fddf260c15d6e25be601abe745ff96f4
OF-3176: Fix NettyConnectionAcceptor start() to restore interrupt flag on InterruptedException
Previously, when start() was interrupted, closeMainChannel() was called but the thread's interrupted status was cleared. This could hide the interruption from higher-level code. Now, the interrupt flag is restored via Thread.currentThread().interrupt(), ensuring that the thread interruption is correctly propagated without changing existing stop/start behavior.- xmppserver/src/main/java/org/jivesoftware/openfire/spi/NettyConnectionAcceptor.java (version dab901d1fddf260c15d6e25be601abe745ff96f4)
-
Guus der Kinderen 369fdc42a7640058459e03c1211c7ae087db02d8
OF-3182: Share Netty thread pools across outbound S2S connections
Previously, each NettySessionInitializer instance created its own NioEventLoopGroup and DefaultEventExecutorGroup, meaning every outbound S2S connection owned its own thread pools for its entire lifetime. This caused unbounded thread growth under load.
Introduce static shared thread pools (sharedIoWorkerGroup and sharedBlockingHandlerExecutor) in NettySessionInitializer, managed via new startSharedResources() and stopSharedResources() static methods. All outbound S2S connections now share a single pair of pools.- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettySessionInitializer.java (version 369fdc42a7640058459e03c1211c7ae087db02d8)
- xmppserver/src/main/java/org/jivesoftware/openfire/spi/ConnectionListener.java (version 369fdc42a7640058459e03c1211c7ae087db02d8)
-
Guus der Kinderen 973bb4afad7ab5de8f9e6b2c18d008d8b7a0e1a0
Migrate properties for Netty socket options to configurable system properties
Replaced inline Netty channel options in NettyConnectionAcceptor with dedicated SystemProperty constants, replacing the older JiveGlobals approach.
The new approach is a bit more type-safe, and is self-documenting.
Added a couple of new properties for values that were up until now hard-coded.- i18n/src/main/resources/openfire_i18n.properties (version 973bb4afad7ab5de8f9e6b2c18d008d8b7a0e1a0)
- i18n/src/main/resources/openfire_i18n_nl.properties (version 973bb4afad7ab5de8f9e6b2c18d008d8b7a0e1a0)
- xmppserver/src/main/java/org/jivesoftware/openfire/spi/NettyConnectionAcceptor.java (version 973bb4afad7ab5de8f9e6b2c18d008d8b7a0e1a0)
-
Guus der Kinderen 822cf56f3f6c1c6a6c9676396a0d755d1314c86e
OF-3176: Fix race condition on outbound S2S stanza handler initialization
Ensure callers can reliably wait for RespondingServerStanzaHandler creation by exposing a future that completes from handlerAdded(). This prevents intermittent failures caused by accessing the handler before it is attached to the Netty pipeline, without introducing blocking or timing-based workarounds.- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettyConnectionHandler.java (version 822cf56f3f6c1c6a6c9676396a0d755d1314c86e)
- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettySessionInitializer.java (version 822cf56f3f6c1c6a6c9676396a0d755d1314c86e)
-
Guus der Kinderen af06bfd5c6dd679f9d85c53608a2f24413bb57d6
OF-3176: Ensure Netty socket acceptor is fully ready before start() returns
NettyConnectionAcceptor.start() previously returned as soon as the server socket was bound. While this guarantees that the port is open, it does not ensure that the Netty boss EventLoop has completed acceptor initialization.
After the recent change to offload blocking handlers to a separate EventExecutorGroup, this timing window became visible in tests: clients connecting immediately after startup could race ahead of acceptor readiness, leading to intermittent failures.
Fix:
- Add an explicit readiness barrier by scheduling a task on the boss EventLoop and waiting for it to execute before returning from start().
- This guarantees that the server channel is bound, registered, and fully initialized on the Netty event loop before accepting connections.
This change provides deterministic startup semantics for both production use and tests, without affecting per-connection pipeline initialization or runtime behavior.- xmppserver/src/main/java/org/jivesoftware/openfire/spi/NettyConnectionAcceptor.java (version af06bfd5c6dd679f9d85c53608a2f24413bb57d6)
-
Guus der Kinderen d93a6433eae83889c7489fb29d9a1280f06679e1
Revert "OF-3180: Offload ConnectionCloseListener invocation to a dedicated thread pool"
The improvement that was introduced by OF-3180 is redundant, now that a fix for OF-3176 is in place.
This reverts commit 965d2d0abb5b0b98fd273cff2b30cf2d0a299c12.- i18n/src/main/resources/openfire_i18n.properties (version d93a6433eae83889c7489fb29d9a1280f06679e1)
- i18n/src/main/resources/openfire_i18n_nl.properties (version d93a6433eae83889c7489fb29d9a1280f06679e1)
- xmppserver/src/main/java/org/jivesoftware/openfire/net/AbstractConnection.java (version d93a6433eae83889c7489fb29d9a1280f06679e1)
- xmppserver/src/main/java/org/jivesoftware/openfire/spi/ConnectionManagerImpl.java (version d93a6433eae83889c7489fb29d9a1280f06679e1)
-
Guus der Kinderen 4d06a4007cfa090f7c4f905c5d02fecbf157055a
OF-3176: Type NettyConnectionHandler with generic StanzaHandler parameter
Replace raw StanzaHandler usage with a generic type parameter to ensure type safety and remove the need for casting in subclasses.- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettyClientConnectionHandler.java (version 4d06a4007cfa090f7c4f905c5d02fecbf157055a)
- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettyComponentConnectionHandler.java (version 4d06a4007cfa090f7c4f905c5d02fecbf157055a)
- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettyConnectionHandler.java (version 4d06a4007cfa090f7c4f905c5d02fecbf157055a)
- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettyMultiplexerConnectionHandler.java (version 4d06a4007cfa090f7c4f905c5d02fecbf157055a)
- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettyOutboundConnectionHandler.java (version 4d06a4007cfa090f7c4f905c5d02fecbf157055a)
- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettyServerConnectionHandler.java (version 4d06a4007cfa090f7c4f905c5d02fecbf157055a)
-
Guus der Kinderen 55d6a1b88ac47567cb316c7d792bd87c360a8851
OF-3176: Guard NettyConnectionHandler.handlerAdded against exceptions to prevent half-initialized channels
Previously, any exception thrown during handlerAdded (for example, in createNettyConnection or createStanzaHandler) could propagate out of the method, potentially leaving the Netty channel in a partially initialized state with missing attributes such as CONNECTION or HANDLER. This commit wraps the handlerAdded logic in a try-catch block, logs any initialization failures, safely closes the channel to avoid inconsistent state, and completes the stanzaHandlerFuture exceptionally if needed. This ensures that pipeline initialization is robust and that channels never remain half-initialized due to unexpected errors.- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettyConnectionHandler.java (version 55d6a1b88ac47567cb316c7d792bd87c360a8851)
-
Guus der Kinderen 67dc67ecf45b35a16632401f07fbfe3b984713d4
OF-3176: Refactor Netty channel initializers to start TLS in channelActive for safe async handling
Previously, DirectTLS startup was performed in initChannel or scheduled during channelRegistered, which could result in race conditions where incoming data arrived before the TLS handshake was initiated, potentially exposing plaintext. This change moves the TLS startup logic to channelActive, ensuring that the channel is fully connected before beginning the handshake. Auto-read is now enabled only after TLS has been successfully started, preventing premature reads. Additionally, references to the SocketChannel (ch) within handlers have been replaced with ctx.channel() for consistency and to avoid subtle bugs. The old channelRegistered auto-read scheduling has been removed, simplifying the pipeline and making the initialization logic safer for both NettySessionInitializer and NettyServerInitializer.- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettySessionInitializer.java (version 67dc67ecf45b35a16632401f07fbfe3b984713d4)
- xmppserver/src/main/java/org/jivesoftware/openfire/spi/NettyServerInitializer.java (version 67dc67ecf45b35a16632401f07fbfe3b984713d4)
-
Guus der Kinderen 412e3991546b3abd619852aa28835c529e17f4fb
OF-3176: Ensure that Netty main channel startup does not block indefinately
This commit adds a (configurable) timeout to the startup of the main channel's startup.- xmppserver/src/main/java/org/jivesoftware/openfire/spi/NettyConnectionAcceptor.java (version 412e3991546b3abd619852aa28835c529e17f4fb)
-
Guus der Kinderen bcd4ee1b9a39f3fd45334efd0739a0cd430f7635
OF-3176: ensure DirectTLS connections propagate channelActive only after handshake completes
Previously, tlsAndAutoReadHandler unconditionally called ctx.fireChannelActive() after starting DirectTLS, causing businessLogicHandler to receive channelActive before the TLS handshake had completed.
After the prior fix that suppressed this premature propagation, a secondary issue emerged: userEventTriggered fired ctx.fireChannelActive() from businessLogicHandler's own context, meaning the event propagated only to handlers after it in the pipeline — so businessLogicHandler itself never received channelActive at all for DirectTLS connections.
Fix by:
- Changing ctx.fireChannelActive() to ctx.pipeline().fireChannelActive() in NettyConnectionHandler.userEventTriggered, so channelActive restarts from the head and reaches all handlers including businessLogicHandler
- Guarding startTLS in tlsAndAutoReadHandler with connection.isEncrypted() to prevent a second TLS initialisation when channelActive re-propagates from the head through that handler
The result is that for DirectTLS connections, businessLogicHandler receives channelActive exactly once, after the handshake has successfully completed.- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettyConnectionHandler.java (version bcd4ee1b9a39f3fd45334efd0739a0cd430f7635)
- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettySessionInitializer.java (version bcd4ee1b9a39f3fd45334efd0739a0cd430f7635)
- xmppserver/src/main/java/org/jivesoftware/openfire/spi/NettyServerInitializer.java (version bcd4ee1b9a39f3fd45334efd0739a0cd430f7635)
-
Guus der Kinderen 0800713492a57c6e5c8cbc9e324dac7b4d836782
OF-3176: Offload blocking Netty handlers to dedicated executor
Introduce a shared blocking handler executor for Netty pipelines to ensure that potentially blocking or long-running operations do not execute on EventLoop threads.
This change separates responsibilities between:
- acceptor (boss) EventLoopGroup
- non-blocking I/O worker EventLoopGroup
- dedicated executor for blocking pipeline handlers
The new executor is shared across all channels created by a NettyConnectionAcceptor and is used for handlers that may perform authentication, routing, persistence, or other blocking work.
This improves throughput and stability under load by preventing EventLoop starvation and aligns Openfire’s Netty usage with Netty best practices.
The connection configuration’s "max thread pool size" is now applied to the dedicated blocking handler executor. Netty EventLoopGroups (acceptor and I/O worker) now use Netty’s default thread sizing, as they are reserved exclusively for non-blocking socket I/O and protocol framing.- documentation/internal-networking.html (version 0800713492a57c6e5c8cbc9e324dac7b4d836782)
- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettyChannelHandlerFactory.java (version 0800713492a57c6e5c8cbc9e324dac7b4d836782)
- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettySessionInitializer.java (version 0800713492a57c6e5c8cbc9e324dac7b4d836782)
- xmppserver/src/main/java/org/jivesoftware/openfire/spi/NettyConnectionAcceptor.java (version 0800713492a57c6e5c8cbc9e324dac7b4d836782)
- xmppserver/src/main/java/org/jivesoftware/openfire/spi/NettyServerInitializer.java (version 0800713492a57c6e5c8cbc9e324dac7b4d836782)
-
Guus der Kinderen 3a15d09db06d25d1ea4a27dc7f362b102cbddb26
Revert "OF-3180: Refactor ConnectionCloseListener implementations for async dispatcher"
The improvement that was introduced by OF-3180 is redundant, now that a fix for OF-3176 is in place.
This reverts commit 562ba69705769fc4ec664c40e67b10defa9c7187.- xmppserver/src/main/java/org/jivesoftware/openfire/SessionManager.java (version 3a15d09db06d25d1ea4a27dc7f362b102cbddb26)
- xmppserver/src/main/java/org/jivesoftware/openfire/net/ComponentStanzaHandler.java (version 3a15d09db06d25d1ea4a27dc7f362b102cbddb26)
- xmppserver/src/main/java/org/jivesoftware/openfire/session/LocalComponentSession.java (version 3a15d09db06d25d1ea4a27dc7f362b102cbddb26)
-
Guus der Kinderen 9ac86ef31c76158c13750dfd2afc0defa12c9d77
OF-3176: Update javadoc for blockingHandlerExecutor per review feedback
The original javadoc was copied from a very similar code structure that was added to NettyConnectionAcceptor.- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettySessionInitializer.java (version 9ac86ef31c76158c13750dfd2afc0defa12c9d77)
-
Guus der Kinderen 5ede3d8f12f41a15399a50a3f911f0c91d19d45d
OF-3176: fix: delay enabling autoRead until business logic handler is ready
Enabling autoRead immediately after firing channelActive created a race condition where incoming data could be dispatched to the pipeline before the business logic handler had finished initialising on the blockingHandlerExecutor, causing sessions to occasionally fail to be established.
Fix by gating autoRead on stanzaHandlerFuture, which completes once the handler has been fully initialised in handlerAdded. The setAutoRead(true) call is submitted back to the EventLoop via eventLoop().execute() to ensure it runs on the correct thread.
Applies to both inbound (NettyServerInitializer) and outbound (NettySessionInitializer) pipelines.- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettySessionInitializer.java (version 5ede3d8f12f41a15399a50a3f911f0c91d19d45d)
- xmppserver/src/main/java/org/jivesoftware/openfire/spi/NettyServerInitializer.java (version 5ede3d8f12f41a15399a50a3f911f0c91d19d45d)
-
Guus der Kinderen 2670f0df84d8a95b6a2bde883c1f7fdc6e01c994
OF-3176: Fix race condition introduced by separate executor for blocking Netty handlers
A recent change switched server-side (NettyServerInitializer) and outbound client (NettySessionInitializer) pipelines to use a separate EventExecutorGroup for blocking handlers, to prevent long-running operations from exhausting the Netty EventLoop (OF-3176).
This introduced a race condition: if data arrived immediately after a channel became active, it could reach the pipeline before the handler was fully registered on the executor, leaving it queued until the executor ran or the acceptor was stopped. Occassional, but flaky, failures of the LocalIncomingServerSessionTest unit tests were a symptom of this race condition.
Fix:
- Disable autoRead on the channel initially.
- Re-enable autoRead only after the channel is fully registered.
This restores reliable processing of incoming data on both server and outbound sessions while still preventing Netty EventLoop starvation from blocking operations.- xmppserver/src/main/java/org/jivesoftware/openfire/nio/NettySessionInitializer.java (version 2670f0df84d8a95b6a2bde883c1f7fdc6e01c994)
- xmppserver/src/main/java/org/jivesoftware/openfire/spi/NettyServerInitializer.java (version 2670f0df84d8a95b6a2bde883c1f7fdc6e01c994)
-
Guus der Kinderen a6677e6dd4d02f90ec65a69a19d9bdd9fa4c7ece
CI: Fix stale Docker image being used in CI tests
Separate the cache-from and cache-to keys in the build-docker job so that each commit writes a fresh cache entry (keyed by SHA) while still reading from the stable hash-based cache to reuse Maven dependency layers.
Also expand the cache key hash to include the Dockerfile and entrypoint.sh, ensuring that changes to any of these files correctly bust the cache.- .github/workflows/continuous-integration-workflow.yml (version a6677e6dd4d02f90ec65a69a19d9bdd9fa4c7ece)
-
Guus der Kinderen 5ee160dd24171ce9c05ab6c1789bf35fd1c5f055
CI: 'xcheck-database-version' does not need the 'build' artifact
This job only reads source files checked out from the repo and runs a shell script. It never uses the compiled distribution or Maven artifacts. The needs: [build, ...] dependency forces it to wait unnecessarily. Removing the build dependency (keeping should-do-database-tests and check_branch) would let it run earlier in parallel.- .github/workflows/continuous-integration-workflow.yml (version 5ee160dd24171ce9c05ab6c1789bf35fd1c5f055)
-
Guus der Kinderen 89a8ebe9fbf534508452175e53cdedd7fd117c9b
CI: 'build-deb-artifact' should have gating
This job depends only on build, not on any test jobs. A broken or failing build could still produce and upload a .deb artifact, which is potentially misleading. It should depend on the same gate as the publish jobs.- .github/workflows/continuous-integration-workflow.yml (version 89a8ebe9fbf534508452175e53cdedd7fd117c9b)
-
Guus der Kinderen 2c8c1fff2b4f01bf9ca3532af333ce850a75ac31
CI: Prevent pulling full history of aioxmpp
The aioxmpp test uses a clone of an unpinned external repository (aioxmpp's). There's no need to pull the full history.- .github/workflows/continuous-integration-workflow.yml (version 2c8c1fff2b4f01bf9ca3532af333ce850a75ac31)
-
Guus der Kinderen 8d2b6d7d63caad7b42f5c3a44a5b352dd8221576
CI: share Docker image between jobs via artifact archive
The earlier fix for reusing Docker images used GHCR as the intermediary, which fails for pull requests from forks due to insufficient registry permissions.
Instead, build the image once in a dedicated `build-docker` job, save it to a gzip-compressed tar archive via `docker save`, and share it as a workflow artifact with a 1-day retention. Downstream jobs (`integration` and `publish-docker`) download and restore the image via `docker load`, requiring no registry access at build or test time.- .github/workflows/continuous-integration-workflow.yml (version 8d2b6d7d63caad7b42f5c3a44a5b352dd8221576)
-
Guus der Kinderen d693bda301e18dda9d682ddac6157ae8cfe1c782
CI: exclude 'test_security_layer' from aioxmpp pending issues in aioxmpp
A recent code change in aioxmpp seems to have broken this test. Exclude it for the time being. See https://codeberg.org/jssfr/aioxmpp/pulls/417 for details.- .github/workflows/continuous-integration-workflow.yml (version d693bda301e18dda9d682ddac6157ae8cfe1c782)
-
Guus der Kinderen 8450871ef0f5c38ceda311d629460d75897f1070
Bump Mockito from 5.4.0 to 5.22.0
This is mainly done to perform cache-busting for the Docker-image build inside CI.- Dockerfile (version 8450871ef0f5c38ceda311d629460d75897f1070)
- xmppserver/pom.xml (version 8450871ef0f5c38ceda311d629460d75897f1070)
-
Guus der Kinderen 82817c4f5894fbfaef1d39d5960a451695dd902f
CI: Add 'integration' as explicit dependency of 'publish-maven' and 'build-and-push-docker'
The publish-maven and build-and-push-docker jobs list many required jobs (aioxmpp, connectivity, etc.) but omit the integration job entirely. This means you could publish a build that failed its integration test suite.- .github/workflows/continuous-integration-workflow.yml (version 82817c4f5894fbfaef1d39d5960a451695dd902f)
-
Guus der Kinderen d31711a887c981b3ca475f9885aeed0259944259
CI: Prevent stale runs
By applying concurrency configuration, multiple pushes in quick successino will prevent queuing up redundant full CI runs.- .github/workflows/continuous-integration-workflow.yml (version d31711a887c981b3ca475f9885aeed0259944259)
-
Guus der Kinderen ae2458550f862570cacb2ff02f86b968fc7f565a
CI: build Docker image once and share across jobs
Previously, the Docker image was built independently in both the `integration` job (locally via `load: true`) and the `build-and-push-docker` job, meaning the image was built twice per CI run with no guarantee both builds produced identical output.
Introduce a new `build-docker` job that builds the image once after `build` completes, pushes it to GHCR tagged as `ci-<sha>`, and exposes the image tag and digest as job outputs.
The `integration` job now depends on `build-docker` and pulls the pre-built image rather than building locally. The `build-and-push-docker` job likewise pulls the same ephemeral image, retags it with final production tags via `docker/metadata-action`, and pushes those. The attestation step now references the digest from `build-docker` rather than a fresh build, ensuring provenance is accurate.
A cleanup step removes the ephemeral `ci-*` tag from GHCR after the final tags are pushed.- .github/workflows/continuous-integration-workflow.yml (version ae2458550f862570cacb2ff02f86b968fc7f565a)