diff --git a/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompSubframeDecoder.java b/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompSubframeDecoder.java index 3ce55f21cb..b4d6a14958 100644 --- a/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompSubframeDecoder.java +++ b/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompSubframeDecoder.java @@ -196,7 +196,7 @@ public class StompSubframeDecoder extends ReplayingDecoder { } private StompCommand readCommand(ByteBuf in) { - String commandStr = readLine(in, maxLineLength); + String commandStr = readLine(in, 16); StompCommand command = null; try { command = StompCommand.valueOf(commandStr); @@ -218,18 +218,11 @@ public class StompSubframeDecoder extends ReplayingDecoder { } private State readHeaders(ByteBuf buffer, StompHeaders headers) { + AppendableCharSequence buf = new AppendableCharSequence(128); for (;;) { - String line = readLine(buffer, maxLineLength); - if (!line.isEmpty()) { - String[] split = line.split(":"); - if (split.length == 2) { - headers.add(split[0], split[1]); - } else if (validateHeaders) { - throw new IllegalArgumentException("a header value or name contains a prohibited character ':'" + - ", " + line); - } - } else { - if (headers.contains(StompHeaders.CONTENT_LENGTH)) { + boolean headerRead = readHeader(headers, buf, buffer); + if (!headerRead) { + if (headers.contains(StompHeaders.CONTENT_LENGTH)) { contentLength = getContentLength(headers, 0); if (contentLength == 0) { return State.FINALIZE_FRAME_READ; @@ -266,21 +259,18 @@ public class StompSubframeDecoder extends ReplayingDecoder { } } - private static String readLine(ByteBuf buffer, int maxLineLength) { - AppendableCharSequence buf = new AppendableCharSequence(128); + private String readLine(ByteBuf buffer, int initialBufferSize) { + AppendableCharSequence buf = new AppendableCharSequence(initialBufferSize); int lineLength = 0; for (;;) { byte nextByte = buffer.readByte(); if (nextByte == StompConstants.CR) { - nextByte = buffer.readByte(); - if (nextByte == StompConstants.LF) { - return buf.toString(); - } + //do nothing } else if (nextByte == StompConstants.LF) { return buf.toString(); } else { if (lineLength >= maxLineLength) { - throw new TooLongFrameException("An STOMP line is larger than " + maxLineLength + " bytes."); + invalidLineLength(); } lineLength ++; buf.append((char) nextByte); @@ -288,6 +278,52 @@ public class StompSubframeDecoder extends ReplayingDecoder { } } + private boolean readHeader(StompHeaders headers, AppendableCharSequence buf, ByteBuf buffer) { + buf.reset(); + int lineLength = 0; + String key = null; + boolean valid = false; + for (;;) { + byte nextByte = buffer.readByte(); + + if (nextByte == StompConstants.COLON && key == null) { + key = buf.toString(); + valid = true; + buf.reset(); + } else if (nextByte == StompConstants.CR) { + //do nothing + } else if (nextByte == StompConstants.LF) { + if (key == null && lineLength == 0) { + return false; + } else if (valid) { + headers.add(key, buf.toString()); + } else if (validateHeaders) { + invalidHeader(key, buf.toString()); + } + return true; + } else { + if (lineLength >= maxLineLength) { + invalidLineLength(); + } + if (nextByte == StompConstants.COLON && key != null) { + valid = false; + } + lineLength ++; + buf.append((char) nextByte); + } + } + } + + private void invalidHeader(String key, String value) { + String line = key != null ? key + ":" + value : value; + throw new IllegalArgumentException("a header value or name contains a prohibited character ':'" + + ", " + line); + } + + private void invalidLineLength() { + throw new TooLongFrameException("An STOMP line is larger than " + maxLineLength + " bytes."); + } + private void resetDecoder() { checkpoint(State.SKIP_CONTROL_CHARACTERS); contentLength = -1;