From 24488f0c2f45952b22f524ae590ad0f1389871b4 Mon Sep 17 00:00:00 2001 From: Kevin Herron Date: Sun, 10 May 2026 06:31:39 -0700 Subject: [PATCH] Preserve customizer handlers at pipeline head after handshake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UascClientAcknowledgeHandler.onAcknowledge previously called addFirst(messageHandler) on the channel pipeline, which displaced any handler installed at position 0 by the client's pipeline customizer (e.g. a PcapWriteHandler added via pipeline.addFirst). Because UascClientMessageHandler is a ByteToMessageCodec, it then consumed inbound ByteBufs before they could reach the displaced customizer handler — silently breaking pcap capture and similar use cases for the remainder of the session. Insert the message handler before DelegatingUascResponseHandler instead of at absolute position 0. The relative ordering is what the codec actually needs, and customizer handlers at the head keep seeing raw wire bytes — matching the symmetric behavior on the server side. Fixes #1740 --- .../client/uasc/UascClientAcknowledgeHandler.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/opc-ua-stack/transport/src/main/java/org/eclipse/milo/opcua/stack/transport/client/uasc/UascClientAcknowledgeHandler.java b/opc-ua-stack/transport/src/main/java/org/eclipse/milo/opcua/stack/transport/client/uasc/UascClientAcknowledgeHandler.java index 0695895fb5..625a036367 100644 --- a/opc-ua-stack/transport/src/main/java/org/eclipse/milo/opcua/stack/transport/client/uasc/UascClientAcknowledgeHandler.java +++ b/opc-ua-stack/transport/src/main/java/org/eclipse/milo/opcua/stack/transport/client/uasc/UascClientAcknowledgeHandler.java @@ -35,6 +35,7 @@ import org.eclipse.milo.opcua.stack.core.types.UaRequestMessageType; import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode; import org.eclipse.milo.opcua.stack.transport.client.ClientApplicationContext; +import org.eclipse.milo.opcua.stack.transport.client.uasc.InboundUascResponseHandler.DelegatingUascResponseHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -254,7 +255,16 @@ private void onAcknowledge(ChannelHandlerContext ctx, ByteBuf buffer) { awaitingHandshake, channelParameters); - ctx.pipeline().addFirst(messageHandler); + // Insert immediately before DelegatingUascResponseHandler rather than at + // position 0, so any pipeline-customizer handlers at the head (e.g. a + // PcapWriteHandler installed via addFirst) keep seeing raw wire bytes. + ChannelHandlerContext responseCtx = + ctx.pipeline().context(DelegatingUascResponseHandler.class); + if (responseCtx != null) { + ctx.pipeline().addBefore(responseCtx.name(), null, messageHandler); + } else { + ctx.pipeline().addFirst(messageHandler); + } }); }