Author: remm Date: Thu Feb 8 21:25:40 2018 New Revision: 1823602 URL: http://svn.apache.org/viewvc?rev=1823602&view=rev Log: Refactoring to reduce duplication.
Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncParser.java tomcat/trunk/java/org/apache/coyote/http2/Http2Parser.java Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncParser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncParser.java?rev=1823602&r1=1823601&r2=1823602&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncParser.java (original) +++ tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncParser.java Thu Feb 8 21:25:40 2018 @@ -19,10 +19,8 @@ package org.apache.coyote.http2; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.CompletionHandler; -import java.nio.charset.StandardCharsets; import java.util.concurrent.TimeUnit; -import org.apache.tomcat.util.buf.ByteBufferUtils; import org.apache.tomcat.util.net.SocketEvent; import org.apache.tomcat.util.net.SocketWrapperBase; import org.apache.tomcat.util.net.SocketWrapperBase.BlockingMode; @@ -80,378 +78,13 @@ class Http2AsyncParser extends Http2Pars } } - // TODO: see how to refactor to avoid duplication - private void readDataFrame(int streamId, int flags, int payloadSize, ByteBuffer buffer) - throws Http2Exception, IOException { - // Process the Stream - int padLength = 0; - - boolean endOfStream = Flags.isEndOfStream(flags); - - int dataLength; - if (Flags.hasPadding(flags)) { - padLength = buffer.get() & 0xFF; - - if (padLength >= payloadSize) { - throw new ConnectionException( - sm.getString("http2Parser.processFrame.tooMuchPadding", connectionId, - Integer.toString(streamId), Integer.toString(padLength), - Integer.toString(payloadSize)), Http2Error.PROTOCOL_ERROR); - } - // +1 is for the padding length byte we just read above - dataLength = payloadSize - (padLength + 1); - } else { - dataLength = payloadSize; - } - - if (log.isDebugEnabled()) { - String padding; - if (Flags.hasPadding(flags)) { - padding = Integer.toString(padLength); - } else { - padding = "none"; - } - log.debug(sm.getString("http2Parser.processFrameData.lengths", connectionId, - Integer.toString(streamId), Integer.toString(dataLength), padding)); - } - - ByteBuffer dest = output.startRequestBodyFrame(streamId, payloadSize); - if (dest == null) { - swallow(streamId, dataLength, false, buffer); - // Process padding before sending any notifications in case padding - // is invalid. - if (padLength > 0) { - swallow(streamId, padLength, true, buffer); - } - if (endOfStream) { - output.receivedEndOfStream(streamId); - } - } else { - synchronized (dest) { - if (dest.remaining() < dataLength) { - swallow(streamId, dataLength, false, buffer); - // Client has sent more data than permitted by Window size - throw new StreamException("Client sent more data than stream window allowed", Http2Error.FLOW_CONTROL_ERROR, streamId); - } - int oldLimit = buffer.limit(); - buffer.limit(buffer.position() + dataLength); - dest.put(buffer); - buffer.limit(oldLimit); - // Process padding before sending any notifications in case - // padding is invalid. - if (padLength > 0) { - swallow(streamId, padLength, true, buffer); - } - if (endOfStream) { - output.receivedEndOfStream(streamId); - } - output.endRequestBodyFrame(streamId); - } - } - if (buffer.hasRemaining()) { - socketWrapper.unRead(buffer); - } - if (padLength > 0) { - output.swallowedPadding(streamId, padLength); - } - } - - - private void readHeadersFrame(int streamId, int flags, int payloadSize, ByteBuffer buffer) - throws Http2Exception, IOException { - - headersEndStream = Flags.isEndOfStream(flags); - - if (hpackDecoder == null) { - hpackDecoder = output.getHpackDecoder(); - } - - try { - hpackDecoder.setHeaderEmitter(output.headersStart(streamId, headersEndStream)); - } catch (StreamException se) { - swallow(streamId, payloadSize, false, buffer); - throw se; - } - - int padLength = 0; - boolean padding = Flags.hasPadding(flags); - boolean priority = Flags.hasPriority(flags); - int optionalLen = 0; - if (padding) { - optionalLen = 1; - } - if (priority) { - optionalLen += 5; - } - if (optionalLen > 0) { - byte[] optional = new byte[optionalLen]; - buffer.get(optional); - int optionalPos = 0; - if (padding) { - padLength = ByteUtil.getOneByte(optional, optionalPos++); - if (padLength >= payloadSize) { - throw new ConnectionException( - sm.getString("http2Parser.processFrame.tooMuchPadding", connectionId, - Integer.toString(streamId), Integer.toString(padLength), - Integer.toString(payloadSize)), Http2Error.PROTOCOL_ERROR); - } - } - if (priority) { - boolean exclusive = ByteUtil.isBit7Set(optional[optionalPos]); - int parentStreamId = ByteUtil.get31Bits(optional, optionalPos); - int weight = ByteUtil.getOneByte(optional, optionalPos + 4) + 1; - output.reprioritise(streamId, parentStreamId, exclusive, weight); - } - - payloadSize -= optionalLen; - payloadSize -= padLength; - } - - readHeaderPayload(streamId, payloadSize, buffer); - - swallow(streamId, padLength, true, buffer); - - if (buffer.hasRemaining()) { - socketWrapper.unRead(buffer); - } - - if (Flags.isEndOfHeaders(flags)) { - onHeadersComplete(streamId); - } else { - headersCurrentStream = streamId; - } - } - - - private void readPriorityFrame(int streamId, ByteBuffer buffer) throws Http2Exception, IOException { - byte[] payload = new byte[5]; - buffer.get(payload); - if (buffer.hasRemaining()) { - socketWrapper.unRead(buffer); - } - - boolean exclusive = ByteUtil.isBit7Set(payload[0]); - int parentStreamId = ByteUtil.get31Bits(payload, 0); - int weight = ByteUtil.getOneByte(payload, 4) + 1; - - if (streamId == parentStreamId) { - throw new StreamException(sm.getString("http2Parser.processFramePriority.invalidParent", - connectionId, Integer.valueOf(streamId)), Http2Error.PROTOCOL_ERROR, streamId); - } - - output.reprioritise(streamId, parentStreamId, exclusive, weight); - } - - - private void readRstFrame(int streamId, ByteBuffer buffer) throws Http2Exception, IOException { - byte[] payload = new byte[4]; - buffer.get(payload); - if (buffer.hasRemaining()) { - socketWrapper.unRead(buffer); - } - - long errorCode = ByteUtil.getFourBytes(payload, 0); - output.reset(streamId, errorCode); - headersCurrentStream = -1; - headersEndStream = false; - } - - - private void readSettingsFrame(int flags, int payloadSize, ByteBuffer buffer) throws Http2Exception, IOException { - boolean ack = Flags.isAck(flags); - if (payloadSize > 0 && ack) { - throw new ConnectionException(sm.getString( - "http2Parser.processFrameSettings.ackWithNonZeroPayload"), - Http2Error.FRAME_SIZE_ERROR); - } - - if (payloadSize != 0) { - // Process the settings - byte[] setting = new byte[6]; - for (int i = 0; i < payloadSize / 6; i++) { - buffer.get(setting); - int id = ByteUtil.getTwoBytes(setting, 0); - long value = ByteUtil.getFourBytes(setting, 2); - output.setting(Setting.valueOf(id), value); - } - } - if (buffer.hasRemaining()) { - socketWrapper.unRead(buffer); - } - output.settingsEnd(ack); - } - - - private void readPingFrame(int flags, ByteBuffer buffer) throws IOException { - // Read the payload - byte[] payload = new byte[8]; - buffer.get(payload); - if (buffer.hasRemaining()) { - socketWrapper.unRead(buffer); - } - output.pingReceive(payload, Flags.isAck(flags)); - } - - - private void readGoawayFrame(int payloadSize, ByteBuffer buffer) throws IOException { - byte[] payload = new byte[payloadSize]; - buffer.get(payload); - if (buffer.hasRemaining()) { - socketWrapper.unRead(buffer); - } - int lastStreamId = ByteUtil.get31Bits(payload, 0); - long errorCode = ByteUtil.getFourBytes(payload, 4); - String debugData = null; - if (payloadSize > 8) { - debugData = new String(payload, 8, payloadSize - 8, StandardCharsets.UTF_8); - } - output.goaway(lastStreamId, errorCode, debugData); - } - - - private void readPushPromiseFrame(int streamId, ByteBuffer buffer) throws Http2Exception { - if (buffer.hasRemaining()) { - socketWrapper.unRead(buffer); - } - throw new ConnectionException(sm.getString("http2Parser.processFramePushPromise", - connectionId, Integer.valueOf(streamId)), Http2Error.PROTOCOL_ERROR); - } - - - private void readWindowUpdateFrame(int streamId, ByteBuffer buffer) throws Http2Exception, IOException { - byte[] payload = new byte[4]; - buffer.get(payload); - if (buffer.hasRemaining()) { - socketWrapper.unRead(buffer); - } - int windowSizeIncrement = ByteUtil.get31Bits(payload, 0); - - if (log.isDebugEnabled()) { - log.debug(sm.getString("http2Parser.processFrameWindowUpdate.debug", connectionId, - Integer.toString(streamId), Integer.toString(windowSizeIncrement))); - } - - // Validate the data - if (windowSizeIncrement == 0) { - if (streamId == 0) { - throw new ConnectionException( - sm.getString("http2Parser.processFrameWindowUpdate.invalidIncrement"), - Http2Error.PROTOCOL_ERROR); - } else { - throw new StreamException( - sm.getString("http2Parser.processFrameWindowUpdate.invalidIncrement"), - Http2Error.PROTOCOL_ERROR, streamId); - } - } - - output.incrementWindowSize(streamId, windowSizeIncrement); - } - - - private void readContinuationFrame(int streamId, int flags, int payloadSize, ByteBuffer buffer) - throws Http2Exception, IOException { - if (headersCurrentStream == -1) { - // No headers to continue - throw new ConnectionException(sm.getString( - "http2Parser.processFrameContinuation.notExpected", connectionId, - Integer.toString(streamId)), Http2Error.PROTOCOL_ERROR); - } - - readHeaderPayload(streamId, payloadSize, buffer); - if (buffer.hasRemaining()) { + protected void unRead(ByteBuffer buffer) { + if (buffer != null && buffer.hasRemaining()) { socketWrapper.unRead(buffer); } - - if (Flags.isEndOfHeaders(flags)) { - headersCurrentStream = -1; - onHeadersComplete(streamId); - } } - - private void readHeaderPayload(int streamId, int payloadSize, ByteBuffer buffer) - throws Http2Exception, IOException { - - if (log.isDebugEnabled()) { - log.debug(sm.getString("http2Parser.processFrameHeaders.payload", connectionId, - Integer.valueOf(streamId), Integer.valueOf(payloadSize))); - } - - int remaining = payloadSize; - - while (remaining > 0) { - if (headerReadBuffer.remaining() == 0) { - // Buffer needs expansion - int newSize; - if (headerReadBuffer.capacity() < payloadSize) { - // First step, expand to the current payload. That should - // cover most cases. - newSize = payloadSize; - } else { - // Header must be spread over multiple frames. Keep doubling - // buffer size until the header can be read. - newSize = headerReadBuffer.capacity() * 2; - } - headerReadBuffer = ByteBufferUtils.expand(headerReadBuffer, newSize); - } - int toRead = Math.min(headerReadBuffer.remaining(), remaining); - // headerReadBuffer in write mode - int oldLimit = buffer.limit(); - buffer.limit(buffer.position() + toRead); - headerReadBuffer.put(buffer); - buffer.limit(oldLimit); - // switch to read mode - headerReadBuffer.flip(); - try { - hpackDecoder.decode(headerReadBuffer); - } catch (HpackException hpe) { - throw new ConnectionException( - sm.getString("http2Parser.processFrameHeaders.decodingFailed"), - Http2Error.COMPRESSION_ERROR, hpe); - } - - // switches to write mode - headerReadBuffer.compact(); - remaining -= toRead; - - if (hpackDecoder.isHeaderCountExceeded()) { - StreamException headerException = new StreamException(sm.getString( - "http2Parser.headerLimitCount", connectionId, Integer.valueOf(streamId)), - Http2Error.ENHANCE_YOUR_CALM, streamId); - hpackDecoder.getHeaderEmitter().setHeaderException(headerException); - } - - if (hpackDecoder.isHeaderSizeExceeded(headerReadBuffer.position())) { - StreamException headerException = new StreamException(sm.getString( - "http2Parser.headerLimitSize", connectionId, Integer.valueOf(streamId)), - Http2Error.ENHANCE_YOUR_CALM, streamId); - hpackDecoder.getHeaderEmitter().setHeaderException(headerException); - } - - if (hpackDecoder.isHeaderSwallowSizeExceeded(headerReadBuffer.position())) { - throw new ConnectionException(sm.getString("http2Parser.headerLimitSize", - connectionId, Integer.valueOf(streamId)), Http2Error.ENHANCE_YOUR_CALM); - } - } - } - - - private void readUnknownFrame(int streamId, FrameType frameType, int flags, int payloadSize, ByteBuffer buffer) - throws IOException { - try { - swallow(streamId, payloadSize, false, buffer); - } catch (ConnectionException e) { - // Will never happen because swallow() is called with mustBeZero set - // to false - } - if (buffer.hasRemaining()) { - socketWrapper.unRead(buffer); - } - output.swallowed(streamId, frameType, flags, payloadSize); - } - - - private void swallow(int streamId, int len, boolean mustBeZero, ByteBuffer buffer) + protected void swallow(int streamId, int len, boolean mustBeZero, ByteBuffer buffer) throws IOException, ConnectionException { if (log.isDebugEnabled()) { log.debug(sm.getString("http2Parser.swallow.debug", connectionId, @@ -554,6 +187,7 @@ class Http2AsyncParser extends Http2Pars try { if (streamException) { swallow(streamId, payloadSize, false, buffers[1]); + unRead(buffers[1]); } else { switch (frameType) { case DATA: @@ -591,8 +225,7 @@ class Http2AsyncParser extends Http2Pars } } } catch (Exception e) { - failed(e, attachment); - return; + error = e; } } if (state == CompletionState.DONE) { @@ -603,8 +236,8 @@ class Http2AsyncParser extends Http2Pars } @Override - public void failed(Throwable exc, Void attachment) { - error = exc; + public void failed(Throwable e, Void attachment) { + error = e; if (state == CompletionState.DONE) { // The call was not completed inline, so must start reading new frames // or process any error Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2Parser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Http2Parser.java?rev=1823602&r1=1823601&r2=1823602&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/Http2Parser.java (original) +++ tomcat/trunk/java/org/apache/coyote/http2/Http2Parser.java Thu Feb 8 21:25:40 2018 @@ -85,50 +85,52 @@ class Http2Parser { try { validateFrame(expected, frameType, streamId, flags, payloadSize); } catch (StreamException se) { - swallow(streamId, payloadSize, false); + swallow(streamId, payloadSize, false, null); throw se; } switch (frameType) { case DATA: - readDataFrame(streamId, flags, payloadSize); + readDataFrame(streamId, flags, payloadSize, null); break; case HEADERS: - readHeadersFrame(streamId, flags, payloadSize); + readHeadersFrame(streamId, flags, payloadSize, null); break; case PRIORITY: - readPriorityFrame(streamId); + readPriorityFrame(streamId, null); break; case RST: - readRstFrame(streamId); + readRstFrame(streamId, null); break; case SETTINGS: - readSettingsFrame(flags, payloadSize); + readSettingsFrame(flags, payloadSize, null); break; case PUSH_PROMISE: - readPushPromiseFrame(streamId); + readPushPromiseFrame(streamId, null); break; case PING: - readPingFrame(flags); + readPingFrame(flags, null); break; case GOAWAY: - readGoawayFrame(payloadSize); + readGoawayFrame(payloadSize, null); break; case WINDOW_UPDATE: - readWindowUpdateFrame(streamId); + readWindowUpdateFrame(streamId, null); break; case CONTINUATION: - readContinuationFrame(streamId, flags, payloadSize); + readContinuationFrame(streamId, flags, payloadSize, null); break; case UNKNOWN: - readUnknownFrame(streamId, frameType, flags, payloadSize); + readUnknownFrame(streamId, frameType, flags, payloadSize, null); } return true; } + protected void unRead(ByteBuffer buffer) { + } - private void readDataFrame(int streamId, int flags, int payloadSize) + protected void readDataFrame(int streamId, int flags, int payloadSize, ByteBuffer buffer) throws Http2Exception, IOException { // Process the Stream int padLength = 0; @@ -137,9 +139,13 @@ class Http2Parser { int dataLength; if (Flags.hasPadding(flags)) { - byte[] b = new byte[1]; - input.fill(true, b); - padLength = b[0] & 0xFF; + if (buffer == null) { + byte[] b = new byte[1]; + input.fill(true, b); + padLength = b[0] & 0xFF; + } else { + padLength = buffer.get() & 0xFF; + } if (padLength >= payloadSize) { throw new ConnectionException( @@ -166,11 +172,11 @@ class Http2Parser { ByteBuffer dest = output.startRequestBodyFrame(streamId, payloadSize); if (dest == null) { - swallow(streamId, dataLength, false); + swallow(streamId, dataLength, false, buffer); // Process padding before sending any notifications in case padding // is invalid. if (padLength > 0) { - swallow(streamId, padLength, true); + swallow(streamId, padLength, true, buffer); } if (endOfStream) { output.receivedEndOfStream(streamId); @@ -178,15 +184,23 @@ class Http2Parser { } else { synchronized (dest) { if (dest.remaining() < dataLength) { - swallow(streamId, dataLength, false); + swallow(streamId, dataLength, false, buffer); + unRead(buffer); // Client has sent more data than permitted by Window size throw new StreamException("Client sent more data than stream window allowed", Http2Error.FLOW_CONTROL_ERROR, streamId); } - input.fill(true, dest, dataLength); + if (buffer == null) { + input.fill(true, dest, dataLength); + } else { + int oldLimit = buffer.limit(); + buffer.limit(buffer.position() + dataLength); + dest.put(buffer); + buffer.limit(oldLimit); + } // Process padding before sending any notifications in case // padding is invalid. if (padLength > 0) { - swallow(streamId, padLength, true); + swallow(streamId, padLength, true, buffer); } if (endOfStream) { output.receivedEndOfStream(streamId); @@ -194,13 +208,14 @@ class Http2Parser { output.endRequestBodyFrame(streamId); } } + unRead(buffer); if (padLength > 0) { output.swallowedPadding(streamId, padLength); } } - private void readHeadersFrame(int streamId, int flags, int payloadSize) + protected void readHeadersFrame(int streamId, int flags, int payloadSize, ByteBuffer buffer) throws Http2Exception, IOException { headersEndStream = Flags.isEndOfStream(flags); @@ -211,7 +226,7 @@ class Http2Parser { try { hpackDecoder.setHeaderEmitter(output.headersStart(streamId, headersEndStream)); } catch (StreamException se) { - swallow(streamId, payloadSize, false); + swallow(streamId, payloadSize, false, buffer); throw se; } @@ -227,7 +242,11 @@ class Http2Parser { } if (optionalLen > 0) { byte[] optional = new byte[optionalLen]; - input.fill(true, optional); + if (buffer == null) { + input.fill(true, optional); + } else { + buffer.get(optional); + } int optionalPos = 0; if (padding) { padLength = ByteUtil.getOneByte(optional, optionalPos++); @@ -249,9 +268,11 @@ class Http2Parser { payloadSize -= padLength; } - readHeaderPayload(streamId, payloadSize); + readHeaderPayload(streamId, payloadSize, buffer); + + swallow(streamId, padLength, true, buffer); - swallow(streamId, padLength, true); + unRead(buffer); if (Flags.isEndOfHeaders(flags)) { onHeadersComplete(streamId); @@ -261,9 +282,14 @@ class Http2Parser { } - private void readPriorityFrame(int streamId) throws Http2Exception, IOException { + protected void readPriorityFrame(int streamId, ByteBuffer buffer) throws Http2Exception, IOException { byte[] payload = new byte[5]; - input.fill(true, payload); + if (buffer == null) { + input.fill(true, payload); + } else { + buffer.get(payload); + unRead(buffer); + } boolean exclusive = ByteUtil.isBit7Set(payload[0]); int parentStreamId = ByteUtil.get31Bits(payload, 0); @@ -278,9 +304,14 @@ class Http2Parser { } - private void readRstFrame(int streamId) throws Http2Exception, IOException { + protected void readRstFrame(int streamId, ByteBuffer buffer) throws Http2Exception, IOException { byte[] payload = new byte[4]; - input.fill(true, payload); + if (buffer == null) { + input.fill(true, payload); + } else { + buffer.get(payload); + unRead(buffer); + } long errorCode = ByteUtil.getFourBytes(payload, 0); output.reset(streamId, errorCode); @@ -289,7 +320,7 @@ class Http2Parser { } - private void readSettingsFrame(int flags, int payloadSize) throws Http2Exception, IOException { + protected void readSettingsFrame(int flags, int payloadSize, ByteBuffer buffer) throws Http2Exception, IOException { boolean ack = Flags.isAck(flags); if (payloadSize > 0 && ack) { throw new ConnectionException(sm.getString( @@ -301,33 +332,49 @@ class Http2Parser { // Process the settings byte[] setting = new byte[6]; for (int i = 0; i < payloadSize / 6; i++) { - input.fill(true, setting); + if (buffer == null) { + input.fill(true, setting); + } else { + buffer.get(setting); + } int id = ByteUtil.getTwoBytes(setting, 0); long value = ByteUtil.getFourBytes(setting, 2); output.setting(Setting.valueOf(id), value); } } + unRead(buffer); output.settingsEnd(ack); } - private void readPushPromiseFrame(int streamId) throws Http2Exception { + protected void readPushPromiseFrame(int streamId, ByteBuffer buffer) throws Http2Exception { + unRead(buffer); throw new ConnectionException(sm.getString("http2Parser.processFramePushPromise", connectionId, Integer.valueOf(streamId)), Http2Error.PROTOCOL_ERROR); } - private void readPingFrame(int flags) throws IOException { + protected void readPingFrame(int flags, ByteBuffer buffer) throws IOException { // Read the payload byte[] payload = new byte[8]; - input.fill(true, payload); + if (buffer == null) { + input.fill(true, payload); + } else { + buffer.get(payload); + unRead(buffer); + } output.pingReceive(payload, Flags.isAck(flags)); } - private void readGoawayFrame(int payloadSize) throws IOException { + protected void readGoawayFrame(int payloadSize, ByteBuffer buffer) throws IOException { byte[] payload = new byte[payloadSize]; - input.fill(true, payload); + if (buffer == null) { + input.fill(true, payload); + } else { + buffer.get(payload); + unRead(buffer); + } int lastStreamId = ByteUtil.get31Bits(payload, 0); long errorCode = ByteUtil.getFourBytes(payload, 4); @@ -339,9 +386,14 @@ class Http2Parser { } - private void readWindowUpdateFrame(int streamId) throws Http2Exception, IOException { + protected void readWindowUpdateFrame(int streamId, ByteBuffer buffer) throws Http2Exception, IOException { byte[] payload = new byte[4]; - input.fill(true, payload); + if (buffer == null) { + input.fill(true, payload); + } else { + buffer.get(payload); + unRead(buffer); + } int windowSizeIncrement = ByteUtil.get31Bits(payload, 0); if (log.isDebugEnabled()) { @@ -366,7 +418,7 @@ class Http2Parser { } - private void readContinuationFrame(int streamId, int flags, int payloadSize) + protected void readContinuationFrame(int streamId, int flags, int payloadSize, ByteBuffer buffer) throws Http2Exception, IOException { if (headersCurrentStream == -1) { // No headers to continue @@ -375,7 +427,8 @@ class Http2Parser { Integer.toString(streamId)), Http2Error.PROTOCOL_ERROR); } - readHeaderPayload(streamId, payloadSize); + readHeaderPayload(streamId, payloadSize, buffer); + unRead(buffer); if (Flags.isEndOfHeaders(flags)) { headersCurrentStream = -1; @@ -384,7 +437,7 @@ class Http2Parser { } - private void readHeaderPayload(int streamId, int payloadSize) + protected void readHeaderPayload(int streamId, int payloadSize, ByteBuffer buffer) throws Http2Exception, IOException { if (log.isDebugEnabled()) { @@ -411,7 +464,14 @@ class Http2Parser { } int toRead = Math.min(headerReadBuffer.remaining(), remaining); // headerReadBuffer in write mode - input.fill(true, headerReadBuffer, toRead); + if (buffer == null) { + input.fill(true, headerReadBuffer, toRead); + } else { + int oldLimit = buffer.limit(); + buffer.limit(buffer.position() + toRead); + headerReadBuffer.put(buffer); + buffer.limit(oldLimit); + } // switch to read mode headerReadBuffer.flip(); try { @@ -448,46 +508,20 @@ class Http2Parser { } - protected void onHeadersComplete(int streamId) throws Http2Exception { - // Any left over data is a compression error - if (headerReadBuffer.position() > 0) { - throw new ConnectionException( - sm.getString("http2Parser.processFrameHeaders.decodingDataLeft"), - Http2Error.COMPRESSION_ERROR); - } - - // Delay validation (and triggering any exception) until this point - // since all the headers still have to be read if a StreamException is - // going to be thrown. - hpackDecoder.getHeaderEmitter().validateHeaders(); - - output.headersEnd(streamId); - - if (headersEndStream) { - output.receivedEndOfStream(streamId); - headersEndStream = false; - } - - // Reset size for new request if the buffer was previously expanded - if (headerReadBuffer.capacity() > Constants.DEFAULT_HEADER_READ_BUFFER_SIZE) { - headerReadBuffer = ByteBuffer.allocate(Constants.DEFAULT_HEADER_READ_BUFFER_SIZE); - } - } - - - private void readUnknownFrame(int streamId, FrameType frameType, int flags, int payloadSize) + protected void readUnknownFrame(int streamId, FrameType frameType, int flags, int payloadSize, ByteBuffer buffer) throws IOException { try { - swallow(streamId, payloadSize, false); + swallow(streamId, payloadSize, false, buffer); } catch (ConnectionException e) { // Will never happen because swallow() is called with mustBeZero set // to false } + unRead(buffer); output.swallowed(streamId, frameType, flags, payloadSize); } - private void swallow(int streamId, int len, boolean mustBeZero) + protected void swallow(int streamId, int len, boolean mustBeZero, ByteBuffer byteBuffer) throws IOException, ConnectionException { if (log.isDebugEnabled()) { log.debug(sm.getString("http2Parser.swallow.debug", connectionId, @@ -516,6 +550,33 @@ class Http2Parser { } } + + protected void onHeadersComplete(int streamId) throws Http2Exception { + // Any left over data is a compression error + if (headerReadBuffer.position() > 0) { + throw new ConnectionException( + sm.getString("http2Parser.processFrameHeaders.decodingDataLeft"), + Http2Error.COMPRESSION_ERROR); + } + + // Delay validation (and triggering any exception) until this point + // since all the headers still have to be read if a StreamException is + // going to be thrown. + hpackDecoder.getHeaderEmitter().validateHeaders(); + + output.headersEnd(streamId); + + if (headersEndStream) { + output.receivedEndOfStream(streamId); + headersEndStream = false; + } + + // Reset size for new request if the buffer was previously expanded + if (headerReadBuffer.capacity() > Constants.DEFAULT_HEADER_READ_BUFFER_SIZE) { + headerReadBuffer = ByteBuffer.allocate(Constants.DEFAULT_HEADER_READ_BUFFER_SIZE); + } + } + /* * Implementation note: --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org