You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ro...@apache.org on 2019/02/28 10:36:16 UTC

[qpid-proton-j] branch master updated: PROTON-1998: add SASL protocol trace logging

This is an automated email from the ASF dual-hosted git repository.

robbie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-proton-j.git


The following commit(s) were added to refs/heads/master by this push:
     new fd58931  PROTON-1998: add SASL protocol trace logging
fd58931 is described below

commit fd58931a95904ffc441c41a5e9dfb6a56091e437
Author: Robbie Gemmell <ro...@apache.org>
AuthorDate: Wed Feb 27 18:45:10 2019 +0000

    PROTON-1998: add SASL protocol trace logging
    
    Changes from Keith Wall with subsequent updates from me.
    
    This closes #31.
    This closes #30 (original changes).
---
 .../qpid/proton/engine/impl/FrameWriter.java       |  9 +-
 .../qpid/proton/engine/impl/ProtocolTracer.java    |  3 +
 .../apache/qpid/proton/engine/impl/SaslImpl.java   |  8 ++
 .../qpid/proton/engine/impl/TransportImpl.java     | 32 ++++---
 .../qpid/proton/engine/impl/FrameWriterTest.java   | 97 ++++++++++++++++------
 .../qpid/proton/engine/impl/SaslImplTest.java      | 63 ++++++++++++++
 .../qpid/proton/engine/impl/TransportImplTest.java | 54 ++++++++++++
 7 files changed, 228 insertions(+), 38 deletions(-)

diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/FrameWriter.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/FrameWriter.java
index b76dc5c..4c037ac 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/FrameWriter.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/FrameWriter.java
@@ -23,6 +23,7 @@ package org.apache.qpid.proton.engine.impl;
 import java.nio.ByteBuffer;
 
 import org.apache.qpid.proton.amqp.Binary;
+import org.apache.qpid.proton.amqp.security.SaslFrameBody;
 import org.apache.qpid.proton.amqp.transport.EmptyFrame;
 import org.apache.qpid.proton.amqp.transport.FrameBody;
 import org.apache.qpid.proton.codec.EncoderImpl;
@@ -151,6 +152,7 @@ class FrameWriter {
     }
 
     private void logFrame(int channel, Object frameBody, ReadableBuffer payload, int payloadSize) {
+        ProtocolTracer tracer = transport.getProtocolTracer();
         if (frameType == AMQP_FRAME_TYPE) {
             ReadableBuffer originalPayload = null;
             if (payload != null) {
@@ -170,10 +172,15 @@ class FrameWriter {
 
             transport.log(TransportImpl.OUTGOING, frame);
 
-            ProtocolTracer tracer = transport.getProtocolTracer();
             if (tracer != null) {
                 tracer.sentFrame(frame);
             }
+        } else {
+            SaslFrameBody body = (SaslFrameBody) frameBody;
+            transport.log(TransportImpl.OUTGOING, body);
+            if (tracer != null) {
+                tracer.sentSaslBody(body);
+            }
         }
     }
 }
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ProtocolTracer.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ProtocolTracer.java
index 92ad598..ff1468c 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ProtocolTracer.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ProtocolTracer.java
@@ -20,6 +20,7 @@
  */
 package org.apache.qpid.proton.engine.impl;
 
+import org.apache.qpid.proton.amqp.security.SaslFrameBody;
 import org.apache.qpid.proton.framing.TransportFrame;
 
 /**
@@ -29,4 +30,6 @@ public interface ProtocolTracer
 {
     public void receivedFrame(TransportFrame transportFrame);
     public void sentFrame(TransportFrame transportFrame);
+    default void receivedSaslBody(SaslFrameBody saslFrameBody) {}
+    default void sentSaslBody(SaslFrameBody saslFrameBody) {}
 }
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SaslImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SaslImpl.java
index fecf7e6..7c17e20 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SaslImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SaslImpl.java
@@ -317,6 +317,14 @@ public class SaslImpl implements Sasl, SaslFrameBody.SaslFrameBodyHandler<Void>,
     @Override
     public void handle(SaslFrameBody frameBody, Binary payload)
     {
+        _transport.log(TransportImpl.INCOMING, frameBody);
+
+        ProtocolTracer tracer = _transport.getProtocolTracer();
+        if( tracer != null )
+        {
+            tracer.receivedSaslBody(frameBody);
+        }
+
         frameBody.invoke(this, payload, null);
     }
 
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportImpl.java
index 9f68260..30e5a2a 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportImpl.java
@@ -30,6 +30,7 @@ import org.apache.qpid.proton.amqp.Binary;
 import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.UnsignedInteger;
 import org.apache.qpid.proton.amqp.UnsignedShort;
+import org.apache.qpid.proton.amqp.security.SaslFrameBody;
 import org.apache.qpid.proton.amqp.transport.Attach;
 import org.apache.qpid.proton.amqp.transport.Begin;
 import org.apache.qpid.proton.amqp.transport.Close;
@@ -1715,20 +1716,29 @@ public class TransportImpl extends EndpointImpl
     void log(String event, TransportFrame frame)
     {
         if (isTraceFramesEnabled()) {
-            StringBuilder msg = new StringBuilder();
-            msg.append("[").append(System.identityHashCode(this)).append(":")
-                .append(frame.getChannel()).append("]");
-            msg.append(" ").append(event).append(" ").append(frame.getBody());
-
-            Binary bin = frame.getPayload();
-            if (bin != null) {
-                msg.append(" (").append(bin.getLength()).append(") ");
-                msg.append(StringUtils.toQuotedString(bin, TRACE_FRAME_PAYLOAD_LENGTH, true));
-            }
-            System.out.println(msg.toString());
+            outputMessage(event, frame.getChannel(), frame.getBody(), frame.getPayload());
+        }
+    }
+
+    void log(final String event, final SaslFrameBody frameBody) {
+        if (isTraceFramesEnabled()) {
+            outputMessage(event, 0, frameBody, null);
         }
     }
 
+    private void outputMessage(String event, int channel, Object frameBody, Binary payload) {
+        StringBuilder msg = new StringBuilder();
+
+        msg.append("[").append(System.identityHashCode(this)).append(":").append(channel).append("] ");
+        msg.append(event).append(" ").append(frameBody);
+        if (payload != null) {
+            msg.append(" (").append(payload.getLength()).append(") ");
+            msg.append(StringUtils.toQuotedString(payload, TRACE_FRAME_PAYLOAD_LENGTH, true));
+        }
+
+        System.out.println(msg.toString());
+    }
+
     boolean isFrameTracingEnabled()
     {
         return (_levels & TRACE_FRM) != 0 || _protocolTracer.get() != null;
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/FrameWriterTest.java b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/FrameWriterTest.java
index 636c7ac..e392e85 100644
--- a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/FrameWriterTest.java
+++ b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/FrameWriterTest.java
@@ -22,13 +22,21 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Random;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.qpid.proton.amqp.Binary;
 import org.apache.qpid.proton.amqp.UnsignedInteger;
+import org.apache.qpid.proton.amqp.security.SaslFrameBody;
+import org.apache.qpid.proton.amqp.security.SaslInit;
 import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode;
 import org.apache.qpid.proton.amqp.transport.Transfer;
 import org.apache.qpid.proton.codec.AMQPDefinedTypes;
@@ -36,6 +44,7 @@ import org.apache.qpid.proton.codec.DecoderImpl;
 import org.apache.qpid.proton.codec.EncoderImpl;
 import org.apache.qpid.proton.codec.ReadableBuffer;
 import org.apache.qpid.proton.framing.TransportFrame;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -251,16 +260,26 @@ public class FrameWriterTest {
 
     @Test
     public void testFrameWriterLogsFramesToTracer() {
-        FrameWriterProtocolTracer tracer = new FrameWriterProtocolTracer();
-        transport.setProtocolTracer(tracer);
+        List<TransportFrame> frames = new ArrayList<>();
+        transport.setProtocolTracer(new ProtocolTracer()
+        {
+            @Override
+            public void sentFrame(final TransportFrame transportFrame)
+            {
+                frames.add(transportFrame);
+            }
+
+            @Override
+            public void receivedFrame(TransportFrame transportFrame) { }
+        });
 
         Transfer transfer = createTransfer();
         FrameWriter framer = new FrameWriter(encoder, Integer.MAX_VALUE, (byte) 0, transport);
 
         framer.writeFrame(16, transfer, bigPayload, new PartialTransferHandler(transfer));
 
-        assertNotNull(tracer.getSentFrame());
-        TransportFrame sentFrame = tracer.getSentFrame();
+        assertEquals(1, frames.size());
+        TransportFrame sentFrame = frames.get(0);
 
         assertEquals(16, sentFrame.getChannel());
         assertTrue(sentFrame.getBody() instanceof Transfer);
@@ -278,17 +297,61 @@ public class FrameWriterTest {
         Transfer transfer = createTransfer();
         FrameWriter framer = new FrameWriter(encoder, Integer.MAX_VALUE, (byte) 0, spy);
 
-        framer.writeFrame(16, transfer, bigPayload, new PartialTransferHandler(transfer));
+        int channel = 16;
+        int payloadLength = bigPayload.capacity();
+
+        framer.writeFrame(channel, transfer, bigPayload, new PartialTransferHandler(transfer));
 
         ArgumentCaptor<TransportFrame> frameCatcher = ArgumentCaptor.forClass(TransportFrame.class);
-        Mockito.verify(spy).log(Mockito.anyString(), frameCatcher.capture());
+        Mockito.verify(spy).log(eq(TransportImpl.OUTGOING), frameCatcher.capture());
 
-        assertEquals(16, frameCatcher.getValue().getChannel());
+        assertEquals(channel, frameCatcher.getValue().getChannel());
         assertTrue(frameCatcher.getValue().getBody() instanceof Transfer);
 
         Binary payload = frameCatcher.getValue().getPayload();
 
-        assertEquals(bigPayload.capacity(), payload.getLength());
+        assertEquals(payloadLength, payload.getLength());
+    }
+
+    @Test
+    public void testFrameWriterLogsSaslFramesToTracer() {
+        List<SaslFrameBody> bodies = new ArrayList<>();
+        transport.setProtocolTracer(new ProtocolTracer()
+        {
+            @Override
+            public void sentSaslBody(final SaslFrameBody saslFrameBody)
+            {
+                bodies.add(saslFrameBody);
+            }
+
+            @Override
+            public void receivedFrame(TransportFrame transportFrame) { }
+
+            @Override
+            public void sentFrame(TransportFrame transportFrame) { }
+        });
+
+        SaslInit init = new SaslInit();
+        FrameWriter framer = new FrameWriter(encoder, Integer.MAX_VALUE,  FrameWriter.SASL_FRAME_TYPE, transport);
+
+        framer.writeFrame(0, init, null, null);
+
+        assertEquals(1, bodies.size());
+        assertTrue(bodies.get(0) instanceof SaslInit);
+    }
+
+    @Test
+    public void testFrameWriterLogsSaslFramesToSystem() {
+        transport.trace(2);
+        TransportImpl spy = spy(transport);
+
+        SaslInit init = new SaslInit();
+        FrameWriter framer = new FrameWriter(encoder, Integer.MAX_VALUE,  FrameWriter.SASL_FRAME_TYPE, spy);
+
+        framer.writeFrame(0, init, null, null);
+
+        verify(spy).log(eq(TransportImpl.OUTGOING),
+                        isA(SaslInit.class));
     }
 
     @Test
@@ -324,24 +387,6 @@ public class FrameWriterTest {
         return transfer;
     }
 
-    private static final class FrameWriterProtocolTracer implements ProtocolTracer {
-
-        private TransportFrame sentFrame;
-
-        public TransportFrame getSentFrame() {
-            return sentFrame;
-        }
-
-        @Override
-        public void receivedFrame(TransportFrame transportFrame) {
-        }
-
-        @Override
-        public void sentFrame(TransportFrame transportFrame) {
-            sentFrame = transportFrame;
-        }
-    }
-
     private static final class PartialTransferHandler implements Runnable {
         private Transfer transfer;
 
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/SaslImplTest.java b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/SaslImplTest.java
index ec524b5..17639c0 100644
--- a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/SaslImplTest.java
+++ b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/SaslImplTest.java
@@ -20,12 +20,24 @@
 */
 package org.apache.qpid.proton.engine.impl;
 
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
 import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.qpid.proton.amqp.Binary;
+import org.apache.qpid.proton.amqp.Symbol;
+import org.apache.qpid.proton.amqp.security.SaslFrameBody;
+import org.apache.qpid.proton.amqp.security.SaslMechanisms;
+import org.apache.qpid.proton.framing.TransportFrame;
 import org.junit.Test;
+import org.mockito.ArgumentCaptor;
 
 public class SaslImplTest {
 
@@ -51,4 +63,55 @@ public class SaslImplTest {
         assertEquals("Unexpected response data", new Binary(expectedResponseBytes), sasl.getChallengeResponse());
     }
 
+    @Test
+    public void testProtocolTracingLogsToTracer() {
+        TransportImpl transport = new TransportImpl();
+        List<SaslFrameBody> bodies = new ArrayList<>();
+        transport.setProtocolTracer(new ProtocolTracer()
+        {
+            @Override
+            public void receivedSaslBody(final SaslFrameBody saslFrameBody)
+            {
+                bodies.add(saslFrameBody);
+            }
+
+            @Override
+            public void receivedFrame(TransportFrame transportFrame) { }
+
+            @Override
+            public void sentFrame(TransportFrame transportFrame) { }
+        });
+
+        SaslImpl sasl = new SaslImpl(transport, 512);
+
+        SaslMechanisms mechs = new SaslMechanisms();
+        mechs.setSaslServerMechanisms(Symbol.valueOf("TESTMECH"));
+
+        assertEquals(0, bodies.size());
+        sasl.handle(mechs, null);
+        assertEquals(1, bodies.size());
+        assertTrue(bodies.get(0) instanceof SaslMechanisms);
+    }
+
+    @Test
+    public void testProtocolTracingLogsToSystem() {
+        TransportImpl transport = new TransportImpl();
+        transport.trace(2);
+
+        TransportImpl spy = spy(transport);
+
+        final String testMechName = "TESTMECH";
+        SaslMechanisms mechs = new SaslMechanisms();
+        mechs.setSaslServerMechanisms(Symbol.valueOf(testMechName));
+
+        SaslImpl sasl = new SaslImpl(spy, 512);
+
+        sasl.handle(mechs, null);
+
+        ArgumentCaptor<SaslMechanisms> frameBodyCatcher = ArgumentCaptor.forClass(SaslMechanisms.class);
+        verify(spy).log(eq(TransportImpl.INCOMING), frameBodyCatcher.capture());
+
+        Symbol[] expectedMechs = new Symbol[] { Symbol.valueOf(testMechName)};
+        assertArrayEquals(expectedMechs, frameBodyCatcher.getValue().getSaslServerMechanisms());
+    }
 }
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/TransportImplTest.java b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/TransportImplTest.java
index 0be219c..3f0da6c 100644
--- a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/TransportImplTest.java
+++ b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/TransportImplTest.java
@@ -29,12 +29,15 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.spy;
 
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Random;
 
 import org.apache.qpid.proton.Proton;
@@ -75,6 +78,7 @@ import org.apache.qpid.proton.message.Message;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 
 public class TransportImplTest
@@ -3637,4 +3641,54 @@ public class TransportImplTest
         assertEquals("Unexpected ErrorCondition returned", ConnectionError.FRAMING_ERROR, transport.getCondition().getCondition());
         assertEquals("Unexpected description returned", "connection aborted", transport.getCondition().getDescription());
     }
+
+    @Test
+    public void testProtocolTracingLogsToTracer()
+    {
+        Connection connection = new ConnectionImpl();
+        List<TransportFrame> frames = new ArrayList<>();
+        _transport.setProtocolTracer(new ProtocolTracer()
+        {
+            @Override
+            public void receivedFrame(final TransportFrame transportFrame)
+            {
+                frames.add(transportFrame);
+            }
+
+            @Override
+            public void sentFrame(TransportFrame transportFrame) { }
+        });
+
+        assertTrue(_transport.isHandlingFrames());
+        _transport.bind(connection);
+
+        assertTrue(_transport.isHandlingFrames());
+        _transport.handleFrame(TRANSPORT_FRAME_OPEN);
+        assertTrue(_transport.isHandlingFrames());
+
+        assertEquals(1, frames.size());
+        TransportFrame transportFrame = frames.get(0);
+        assertTrue(transportFrame.getBody() instanceof Open);
+        assertEquals(CHANNEL_ID, transportFrame.getChannel());
+    }
+
+    @Test
+    public void testProtocolTracingLogsToSystem() {
+        Connection connection = new ConnectionImpl();
+        TransportImpl spy = spy(_transport);
+
+        assertTrue(spy.isHandlingFrames());
+        spy.bind(connection);
+
+        assertTrue(spy.isHandlingFrames());
+        spy.handleFrame(TRANSPORT_FRAME_OPEN);
+        assertTrue(spy.isHandlingFrames());
+
+        ArgumentCaptor<TransportFrame> frameCatcher = ArgumentCaptor.forClass(TransportFrame.class);
+        Mockito.verify(spy).log(eq(TransportImpl.INCOMING), frameCatcher.capture());
+
+        assertEquals(TRANSPORT_FRAME_OPEN.getChannel(), frameCatcher.getValue().getChannel());
+        assertTrue(frameCatcher.getValue().getBody() instanceof Open);
+        assertNull(frameCatcher.getValue().getPayload());
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org