https://issues.apache.org/jira/browse/AMQ-6526 - fix <Unknown> Stomp operation in ProtocolException.

closes #217
This commit is contained in:
Torsten Mielke 2016-12-06 14:32:47 +01:00 committed by gtully
parent e3d698b9d9
commit 9e35778943
2 changed files with 157 additions and 2 deletions

View File

@ -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;
}
}

View File

@ -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;
}
}