Repository: activemq Updated Branches: refs/heads/master e3d698b9d -> 9e3577894
https://issues.apache.org/jira/browse/AMQ-6526 - fix <Unknown> Stomp operation in ProtocolException. closes #217 Project: http://git-wip-us.apache.org/repos/asf/activemq/repo Commit: http://git-wip-us.apache.org/repos/asf/activemq/commit/9e357789 Tree: http://git-wip-us.apache.org/repos/asf/activemq/tree/9e357789 Diff: http://git-wip-us.apache.org/repos/asf/activemq/diff/9e357789 Branch: refs/heads/master Commit: 9e3577894327d8c78bc52bb5f77650af0ceb095b Parents: e3d698b Author: Torsten Mielke <[email protected]> Authored: Tue Dec 6 14:32:47 2016 +0100 Committer: gtully <[email protected]> Committed: Tue Dec 6 13:52:06 2016 +0000 ---------------------------------------------------------------------- .../activemq/transport/stomp/StompCodec.java | 8 +- .../stomp/StompNIOSSLLargeMessageTest.java | 151 +++++++++++++++++++ 2 files changed, 157 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/activemq/blob/9e357789/activemq-stomp/src/main/java/org/apache/activemq/transport/stomp/StompCodec.java ---------------------------------------------------------------------- diff --git a/activemq-stomp/src/main/java/org/apache/activemq/transport/stomp/StompCodec.java b/activemq-stomp/src/main/java/org/apache/activemq/transport/stomp/StompCodec.java index 3581d3b..54ec21a 100644 --- a/activemq-stomp/src/main/java/org/apache/activemq/transport/stomp/StompCodec.java +++ b/activemq-stomp/src/main/java/org/apache/activemq/transport/stomp/StompCodec.java @@ -101,11 +101,15 @@ public class StompCodec { } else { currentCommand.write(b); if (currentCommand.size() > wireFormat.getMaxDataLength()) { - transport.doConsume(new StompFrameError(new ProtocolException("The maximum data length was exceeded", true))); + StompFrameError errorFrame = new StompFrameError(new ProtocolException("The maximum data length was exceeded", true)); + errorFrame.setAction(this.action); + transport.doConsume(errorFrame); return; } if (frameSize.incrementAndGet() > wireFormat.getMaxFrameSize()) { - transport.doConsume(new StompFrameError(new ProtocolException("The maximum frame size was exceeded", true))); + StompFrameError errorFrame = new StompFrameError(new ProtocolException("The maximum frame size was exceeded", true)); + errorFrame.setAction(this.action); + transport.doConsume(errorFrame); return; } } http://git-wip-us.apache.org/repos/asf/activemq/blob/9e357789/activemq-stomp/src/test/java/org/apache/activemq/transport/stomp/StompNIOSSLLargeMessageTest.java ---------------------------------------------------------------------- diff --git a/activemq-stomp/src/test/java/org/apache/activemq/transport/stomp/StompNIOSSLLargeMessageTest.java b/activemq-stomp/src/test/java/org/apache/activemq/transport/stomp/StompNIOSSLLargeMessageTest.java new file mode 100644 index 0000000..d600728 --- /dev/null +++ b/activemq-stomp/src/test/java/org/apache/activemq/transport/stomp/StompNIOSSLLargeMessageTest.java @@ -0,0 +1,151 @@ +package org.apache.activemq.transport.stomp; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.net.Socket; + +import org.apache.activemq.command.ActiveMQQueue; +import org.apache.log4j.Appender; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.Connection; +import javax.jms.Session; +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocketFactory; + +import org.apache.activemq.util.DefaultTestAppender; + +/** + * Testcase for AMQ-6526. + * Checks if the \<Unknown\> in the Stomp ProtocolException is replaced + * with the proper Stomp operation. + * + */ +public class StompNIOSSLLargeMessageTest extends StompTestSupport { + + protected static final Logger LOG = LoggerFactory.getLogger(StompNIOSSLLargeMessageTest.class); + private Connection connection; + private Session session; + private ActiveMQQueue queue; + + // flag to control if the bug in AMQ-XXXX got reproduced. + private boolean gotUnknownOperationInLog = false; + + protected int stompFrameSize = 110000000; //slightly over 105 MB + + // custom Log4J appender so we can filter the logging output in this test. + protected Appender appender = new DefaultTestAppender() { + //@Override + public void doAppend(org.apache.log4j.spi.LoggingEvent event) { + if (event.getMessage().toString().contains("<Unknown>") && + event.getMessage().toString().contains("The maximum data length was exceeded")) { + gotUnknownOperationInLog = true; + } + } + }; + + + @Override + protected boolean isUseTcpConnector() { + return false; + } + + + @Override + protected boolean isUseNioPlusSslConnector() { + return true; + } + + + @Override + protected Socket createSocket() throws IOException { + SocketFactory factory = SSLSocketFactory.getDefault(); + return factory.createSocket("127.0.0.1", this.nioSslPort); + } + + + @Override + public void setUp() throws Exception { + super.setUp(); + + // register custom Log4J Appender + org.apache.log4j.Logger.getRootLogger().addAppender(appender); + + stompConnect(); + connection = cf.createConnection("system", "manager"); + session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + queue = new ActiveMQQueue(getQueueName()); + connection.start(); + } + + + @Override + public void tearDown() throws Exception { + // unregister Log4J appender + org.apache.log4j.Logger.getRootLogger().removeAppender(appender); + } + + + /** + * Sends a Stomp message larger than maxDataLength bytes. + * Expects to receive an exception from the broker. + * The broker will throw an Stomp ProtocolException of type + * "Exception occurred processing: SEND -> + * org.apache.activemq.transport.stomp.ProtocolException: + * The maximum data length was exceeded" + * + * Before bug AMQ-6526 this exception would contain \<Unkown\> for the + * operation name. With the fix it should print the Stomp operation. + * + * @throws Exception + */ + @Test(timeout = 6000000) + public void testSendMessageBytes() throws Exception { + + String frame = "CONNECT\n" + "login:system\n" + "passcode:manager\n" + + "accept-version:1.1" + "\n\n" + Stomp.NULL; + stompConnection.sendFrame(frame); + + frame = stompConnection.receiveFrame(); + assertTrue(frame.startsWith("CONNECTED")); + + frame = "SEND\n" + + "value:newest" + "\n" + + "value:older" + "\n" + + "value:oldest" + "\n" + + "destination:/queue/" + getQueueName() + + "\n\n"; + + byte[] buffer = createLargeByteBuffer(stompFrameSize); + try { + stompConnection.sendFrame(frame, buffer); + } catch (Exception ex) { + LOG.error(ex.getMessage()); + } + assertFalse("Stomp ProtocolException still contains <Unknown> operation.", gotUnknownOperationInLog); + } + + + /** + * Creates a large byte buffer and fills it with char 'X' except for the + * last byte, it gets value 0x0 assigned. + * + * @param size - the size of the array to be created. + * @return + */ + protected byte[] createLargeByteBuffer(int size) { + byte[] buffer = new byte[size]; + for (int i=0; i<size; i++) { + buffer[i] = (char) 'X'; + } + //insert trailing 0x0 + buffer[size-1] = 0; + LOG.info("Created byte buffer of size {} starting with content {}", + size, + new String(buffer,0,20)); + return buffer; + } +}
