diff --git a/jetty-http3/http3-client/src/main/java/module-info.java b/jetty-http3/http3-client/src/main/java/module-info.java index b12dfab5bf4..6fa6a7002cc 100644 --- a/jetty-http3/http3-client/src/main/java/module-info.java +++ b/jetty-http3/http3-client/src/main/java/module-info.java @@ -20,7 +20,7 @@ module org.eclipse.jetty.http3.client requires transitive org.eclipse.jetty.http3.qpack; requires transitive org.eclipse.jetty.io; requires transitive org.eclipse.jetty.quic.common; - requires org.eclipse.jetty.quic.client; + requires transitive org.eclipse.jetty.quic.client; requires transitive org.eclipse.jetty.util; requires org.slf4j; } diff --git a/jetty-http3/http3-client/src/main/java/org/eclipse/jetty/http3/client/HTTP3ClientConnectionFactory.java b/jetty-http3/http3-client/src/main/java/org/eclipse/jetty/http3/client/HTTP3ClientConnectionFactory.java index 91ab5f80987..4dc9c19675d 100644 --- a/jetty-http3/http3-client/src/main/java/org/eclipse/jetty/http3/client/HTTP3ClientConnectionFactory.java +++ b/jetty-http3/http3-client/src/main/java/org/eclipse/jetty/http3/client/HTTP3ClientConnectionFactory.java @@ -77,7 +77,7 @@ public class HTTP3ClientConnectionFactory implements ClientConnectionFactory, Pr long streamId = streamEndPoint.getStreamId(); ClientHTTP3Session http3Session = (ClientHTTP3Session)streamEndPoint.getQuicSession().getProtocolSession(); // TODO: Parser may be created internally, if I pass the QuicStreamEndPoint and ClientHTTP3Session. - MessageParser parser = new MessageParser(streamId, http3Session.getQpackDecoder()); - return new HTTP3Connection(streamEndPoint, http3Session.getQuicSession().getExecutor(), http3Session.getQuicSession().getByteBufferPool(), parser, http3Session.getSessionClient()); + MessageParser parser = new MessageParser(http3Session.getSessionClient(), http3Session.getQpackDecoder(), streamId, streamEndPoint::isStreamFinished); + return new HTTP3Connection(streamEndPoint, http3Session.getQuicSession().getExecutor(), http3Session.getQuicSession().getByteBufferPool(), parser); } } diff --git a/jetty-http3/http3-common/src/main/java/module-info.java b/jetty-http3/http3-common/src/main/java/module-info.java index 47b734a3bab..c9ac9cf6815 100644 --- a/jetty-http3/http3-common/src/main/java/module-info.java +++ b/jetty-http3/http3-common/src/main/java/module-info.java @@ -22,9 +22,9 @@ module org.eclipse.jetty.http3.common exports org.eclipse.jetty.http3.internal; requires transitive org.eclipse.jetty.http; - requires org.eclipse.jetty.http3.qpack; + requires transitive org.eclipse.jetty.http3.qpack; requires org.eclipse.jetty.io; - requires org.eclipse.jetty.quic.common; + requires transitive org.eclipse.jetty.quic.common; requires org.eclipse.jetty.util; requires org.slf4j; } diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/ControlConnection.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/ControlConnection.java index 1769bc5433b..6524cec3315 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/ControlConnection.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/ControlConnection.java @@ -16,11 +16,7 @@ package org.eclipse.jetty.http3.internal; import java.nio.ByteBuffer; import java.util.concurrent.Executor; -import org.eclipse.jetty.http3.frames.Frame; -import org.eclipse.jetty.http3.frames.FrameType; -import org.eclipse.jetty.http3.frames.SettingsFrame; import org.eclipse.jetty.http3.internal.parser.ControlParser; -import org.eclipse.jetty.http3.internal.parser.ParserListener; import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.Connection; @@ -37,16 +33,14 @@ public class ControlConnection extends AbstractConnection implements Connection. private final ByteBufferPool byteBufferPool; private final ControlParser parser; - private final ParserListener listener; private boolean useInputDirectByteBuffers = true; private ByteBuffer buffer; - public ControlConnection(EndPoint endPoint, Executor executor, ByteBufferPool byteBufferPool, ControlParser parser, ParserListener listener) + public ControlConnection(EndPoint endPoint, Executor executor, ByteBufferPool byteBufferPool, ControlParser parser) { super(endPoint, executor); this.byteBufferPool = byteBufferPool; this.parser = parser; - this.listener = listener; } public boolean isUseInputDirectByteBuffers() @@ -90,13 +84,7 @@ public class ControlConnection extends AbstractConnection implements Connection. while (true) { // Parse first in case of bytes from the upgrade. - while (buffer.hasRemaining()) - { - Frame frame = parser.parse(buffer); - if (frame == null) - break; - notifyFrame(frame); - } + parser.parse(buffer); // Then read from the EndPoint. int filled = getEndPoint().fill(buffer); @@ -128,33 +116,4 @@ public class ControlConnection extends AbstractConnection implements Connection. getEndPoint().close(x); } } - - private void notifyFrame(Frame frame) - { - FrameType frameType = frame.getFrameType(); - switch (frameType) - { - case SETTINGS: - { - notifySettings((SettingsFrame)frame); - break; - } - default: - { - throw new UnsupportedOperationException("unsupported frame type " + frameType); - } - } - } - - private void notifySettings(SettingsFrame frame) - { - try - { - listener.onSettings(frame); - } - catch (Throwable x) - { - LOG.info("failure notifying listener {}", listener, x); - } - } } diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/HTTP3Connection.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/HTTP3Connection.java index e7c26ed29d9..83de4429e7a 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/HTTP3Connection.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/HTTP3Connection.java @@ -16,12 +16,7 @@ package org.eclipse.jetty.http3.internal; import java.nio.ByteBuffer; import java.util.concurrent.Executor; -import org.eclipse.jetty.http3.frames.DataFrame; -import org.eclipse.jetty.http3.frames.Frame; -import org.eclipse.jetty.http3.frames.FrameType; -import org.eclipse.jetty.http3.frames.HeadersFrame; import org.eclipse.jetty.http3.internal.parser.MessageParser; -import org.eclipse.jetty.http3.internal.parser.ParserListener; import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.quic.common.QuicStreamEndPoint; @@ -34,15 +29,13 @@ public class HTTP3Connection extends AbstractConnection private final ByteBufferPool byteBufferPool; private final MessageParser parser; - private final ParserListener listener; private boolean useInputDirectByteBuffers = true; - public HTTP3Connection(QuicStreamEndPoint endPoint, Executor executor, ByteBufferPool byteBufferPool, MessageParser parser, ParserListener listener) + public HTTP3Connection(QuicStreamEndPoint endPoint, Executor executor, ByteBufferPool byteBufferPool, MessageParser parser) { super(endPoint, executor); this.byteBufferPool = byteBufferPool; this.parser = parser; - this.listener = listener; } public boolean isUseInputDirectByteBuffers() @@ -76,17 +69,7 @@ public class HTTP3Connection extends AbstractConnection if (filled > 0) { - while (buffer.hasRemaining()) - { - Frame frame = parser.parse(buffer); - if (frame == null) - break; - if (frame instanceof HeadersFrame) - frame = ((HeadersFrame)frame).withLast(getEndPoint().isInputShutdown()); - else if (frame instanceof DataFrame) - frame = ((DataFrame)frame).withLast(getEndPoint().isInputShutdown()); - notifyFrame(frame); - } + parser.parse(buffer); } else if (filled == 0) { @@ -110,52 +93,4 @@ public class HTTP3Connection extends AbstractConnection getEndPoint().close(x); } } - - private void notifyFrame(Frame frame) - { - FrameType frameType = frame.getFrameType(); - switch (frameType) - { - case HEADERS: - { - notifyHeaders((HeadersFrame)frame); - break; - } - case DATA: - { - notifyData((DataFrame)frame); - break; - } - default: - { - throw new UnsupportedOperationException("unsupported frame type " + frameType); - } - } - } - - private void notifyHeaders(HeadersFrame frame) - { - try - { - long streamId = ((QuicStreamEndPoint)getEndPoint()).getStreamId(); - listener.onHeaders(streamId, frame); - } - catch (Throwable x) - { - LOG.info("failure notifying listener {}", listener, x); - } - } - - private void notifyData(DataFrame frame) - { - try - { - long streamId = ((QuicStreamEndPoint)getEndPoint()).getStreamId(); - listener.onData(streamId, frame); - } - catch (Throwable x) - { - LOG.info("failure notifying listener {}", listener, x); - } - } } diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/InstructionConnection.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/InstructionConnection.java index e48788e828e..9d398527a55 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/InstructionConnection.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/InstructionConnection.java @@ -1,3 +1,16 @@ +// +// ======================================================================== +// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + package org.eclipse.jetty.http3.internal; import java.nio.ByteBuffer; diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/UnidirectionalStreamConnection.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/UnidirectionalStreamConnection.java index d3a55736166..0e44e35c21c 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/UnidirectionalStreamConnection.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/UnidirectionalStreamConnection.java @@ -127,8 +127,8 @@ public class UnidirectionalStreamConnection extends AbstractConnection implement { case ControlConnection.STREAM_TYPE: { - ControlParser parser = new ControlParser(); - ControlConnection newConnection = new ControlConnection(getEndPoint(), getExecutor(), byteBufferPool, parser, listener); + ControlParser parser = new ControlParser(listener); + ControlConnection newConnection = new ControlConnection(getEndPoint(), getExecutor(), byteBufferPool, parser); newConnection.setInputBufferSize(getInputBufferSize()); newConnection.setUseInputDirectByteBuffers(isUseInputDirectByteBuffers()); if (LOG.isDebugEnabled()) diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/BodyParser.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/BodyParser.java index 87875ca91f3..37bcebaa095 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/BodyParser.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/BodyParser.java @@ -16,7 +16,10 @@ package org.eclipse.jetty.http3.internal.parser; import java.nio.ByteBuffer; import org.eclipse.jetty.http3.ErrorCode; -import org.eclipse.jetty.http3.frames.Frame; +import org.eclipse.jetty.http3.frames.SettingsFrame; +import org.eclipse.jetty.util.BufferUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** *
The base parser for the frame body of HTTP/3 frames.
@@ -27,18 +30,20 @@ import org.eclipse.jetty.http3.frames.Frame; */ public abstract class BodyParser { - private final long streamId; - private final HeaderParser headerParser; + private static final Logger LOG = LoggerFactory.getLogger(BodyParser.class); - protected BodyParser(long streamId, HeaderParser headerParser) + private final HeaderParser headerParser; + private final ParserListener listener; + + protected BodyParser(HeaderParser headerParser, ParserListener listener) { - this.streamId = streamId; this.headerParser = headerParser; + this.listener = listener; } - protected long getStreamId() + protected ParserListener getParserListener() { - return streamId; + return listener; } protected long getBodyLength() @@ -47,18 +52,60 @@ public abstract class BodyParser } /** - *Parses the frame body bytes in the given {@code buffer}, producing a {@link Frame}.
- *Only the frame body bytes are consumed, therefore when this method returns, the buffer - * may contain unconsumed bytes, for example for other frames.
+ *Parses the frame body bytes in the given {@code buffer}.
+ *Only the frame body bytes are consumed, therefore when this method returns, + * the buffer may contain unconsumed bytes, for example for other frames.
* * @param buffer the buffer to parse - * @return the parsed frame if all the frame body bytes were parsed, or an error frame, - * or null if not enough frame body bytes were present in the buffer + * @return true if all the frame body bytes were parsed; + * false if not enough frame body bytes were present in the buffer */ - public abstract Frame parse(ByteBuffer buffer) throws ParseException; + public abstract boolean parse(ByteBuffer buffer); - protected Frame emptyBody(ByteBuffer buffer) throws ParseException + protected void emptyBody(ByteBuffer buffer) { - throw new ParseException(ErrorCode.PROTOCOL_ERROR.code(), "invalid_frame"); + sessionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code(), "invalid_frame"); + } + + protected void sessionFailure(ByteBuffer buffer, int error, String reason) + { + BufferUtil.clear(buffer); + notifySessionFailure(error, reason); + } + + protected void notifySessionFailure(int error, String reason) + { + try + { + listener.onSessionFailure(error, reason); + } + catch (Throwable x) + { + LOG.info("failure while notifying listener {}", listener, x); + } + } + + protected void notifyStreamFailure(long streamId, int error, String reason) + { + try + { + listener.onStreamFailure(streamId, error, reason); + } + catch (Throwable x) + { + LOG.info("failure while notifying listener {}", listener, x); + } + } + + protected void notifySettings(SettingsFrame frame) + { + try + { + listener.onSettings(frame); + } + catch (Throwable x) + { + LOG.info("failure while notifying listener {}", listener, x); + } } } diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/CancelPushBodyParser.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/CancelPushBodyParser.java index 5d829246838..3154afc0342 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/CancelPushBodyParser.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/CancelPushBodyParser.java @@ -15,17 +15,15 @@ package org.eclipse.jetty.http3.internal.parser; import java.nio.ByteBuffer; -import org.eclipse.jetty.http3.frames.Frame; - public class CancelPushBodyParser extends BodyParser { - public CancelPushBodyParser(HeaderParser headerParser) + public CancelPushBodyParser(HeaderParser headerParser, ParserListener listener) { - super(1, headerParser); + super(headerParser, listener); } @Override - public Frame parse(ByteBuffer buffer) + public boolean parse(ByteBuffer buffer) { throw new UnsupportedOperationException(); } diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/ControlParser.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/ControlParser.java index 176a325f727..7e6260a1e5b 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/ControlParser.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/ControlParser.java @@ -16,7 +16,6 @@ package org.eclipse.jetty.http3.internal.parser; import java.nio.ByteBuffer; import org.eclipse.jetty.http3.ErrorCode; -import org.eclipse.jetty.http3.frames.Frame; import org.eclipse.jetty.http3.frames.FrameType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,14 +34,14 @@ public class ControlParser private final BodyParser unknownBodyParser; private State state = State.HEADER; - public ControlParser() + public ControlParser(ParserListener listener) { this.headerParser = new HeaderParser(); - this.bodyParsers[FrameType.CANCEL_PUSH.type()] = new CancelPushBodyParser(headerParser); - this.bodyParsers[FrameType.SETTINGS.type()] = new SettingsBodyParser(headerParser); - this.bodyParsers[FrameType.GOAWAY.type()] = new GoAwayBodyParser(headerParser); - this.bodyParsers[FrameType.MAX_PUSH_ID.type()] = new MaxPushIdBodyParser(headerParser); - this.unknownBodyParser = new UnknownBodyParser(headerParser); + this.bodyParsers[FrameType.CANCEL_PUSH.type()] = new CancelPushBodyParser(headerParser, listener); + this.bodyParsers[FrameType.SETTINGS.type()] = new SettingsBodyParser(headerParser, listener); + this.bodyParsers[FrameType.GOAWAY.type()] = new GoAwayBodyParser(headerParser, listener); + this.bodyParsers[FrameType.MAX_PUSH_ID.type()] = new MaxPushIdBodyParser(headerParser, listener); + this.unknownBodyParser = new UnknownBodyParser(headerParser, listener); } private void reset() @@ -56,7 +55,7 @@ public class ControlParser * * @param buffer the buffer to parse */ - public Frame parse(ByteBuffer buffer) throws ParseException + public void parse(ByteBuffer buffer) { try { @@ -71,7 +70,7 @@ public class ControlParser state = State.BODY; break; } - return null; + return; } case BODY: { @@ -85,25 +84,26 @@ public class ControlParser // TODO: enforce only control frames, but ignore unknown. if (LOG.isDebugEnabled()) LOG.debug("ignoring unknown frame type {}", Integer.toHexString(frameType)); - Frame frame = unknownBodyParser.parse(buffer); - if (frame == null) - return null; + if (!unknownBodyParser.parse(buffer)) + return; reset(); - break; } else { - Frame frame; if (headerParser.getFrameLength() == 0) - frame = bodyParser.emptyBody(buffer); + { + bodyParser.emptyBody(buffer); + } else - frame = bodyParser.parse(buffer); + { + if (!bodyParser.parse(buffer)) + return; + } if (LOG.isDebugEnabled()) LOG.debug("parsed {} frame body from {}", FrameType.from(frameType), buffer); - if (frame != null) - reset(); - return frame; + reset(); } + break; } default: { @@ -112,22 +112,20 @@ public class ControlParser } } } - catch (ParseException x) - { - if (LOG.isDebugEnabled()) - LOG.debug("parse failed", x); - buffer.clear(); - throw x; - } catch (Throwable x) { if (LOG.isDebugEnabled()) LOG.debug("parse failed", x); buffer.clear(); - throw new ParseException(ErrorCode.INTERNAL_ERROR.code(), "parser_error", true, x); + connectionFailure(buffer, ErrorCode.INTERNAL_ERROR.code(), "parser_error"); } } + private void connectionFailure(ByteBuffer buffer, int error, String reason) + { + unknownBodyParser.sessionFailure(buffer, error, reason); + } + private enum State { HEADER, BODY diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/DataBodyParser.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/DataBodyParser.java index 9a5f811b26d..3ec4c5df0f6 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/DataBodyParser.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/DataBodyParser.java @@ -14,9 +14,9 @@ package org.eclipse.jetty.http3.internal.parser; import java.nio.ByteBuffer; +import java.util.function.BooleanSupplier; import org.eclipse.jetty.http3.frames.DataFrame; -import org.eclipse.jetty.http3.frames.Frame; import org.eclipse.jetty.util.BufferUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,12 +25,16 @@ public class DataBodyParser extends BodyParser { private static final Logger LOG = LoggerFactory.getLogger(DataBodyParser.class); + private final long streamId; + private final BooleanSupplier isLast; private State state = State.INIT; private long length; - public DataBodyParser(long streamId, HeaderParser headerParser) + public DataBodyParser(HeaderParser headerParser, ParserListener listener, long streamId, BooleanSupplier isLast) { - super(streamId, headerParser); + super(headerParser, listener); + this.streamId = streamId; + this.isLast = isLast; } private void reset() @@ -40,13 +44,13 @@ public class DataBodyParser extends BodyParser } @Override - protected Frame emptyBody(ByteBuffer buffer) + protected void emptyBody(ByteBuffer buffer) { - return onData(BufferUtil.EMPTY_BUFFER, false); + onData(BufferUtil.EMPTY_BUFFER, false); } @Override - public Frame parse(ByteBuffer buffer) + public boolean parse(ByteBuffer buffer) { while (buffer.hasRemaining()) { @@ -72,12 +76,14 @@ public class DataBodyParser extends BodyParser if (length == 0) { reset(); - return onData(slice, false); + onData(slice, false); + return true; } else { // We got partial data, simulate a smaller frame, and stay in DATA state. - return onData(slice, true); + onData(slice, true); + break; } } default: @@ -86,15 +92,28 @@ public class DataBodyParser extends BodyParser } } } - return null; + return false; } - private DataFrame onData(ByteBuffer buffer, boolean fragment) + private void onData(ByteBuffer buffer, boolean fragment) { - DataFrame frame = new DataFrame(buffer, true); + DataFrame frame = new DataFrame(buffer, isLast.getAsBoolean()); if (LOG.isDebugEnabled()) - LOG.debug("notifying synthetic={} {}#{}", fragment, frame, getStreamId()); - return frame; + LOG.debug("notifying synthetic={} {}#{}", fragment, frame, streamId); + notifyData(frame); + } + + private void notifyData(DataFrame frame) + { + ParserListener listener = getParserListener(); + try + { + listener.onData(streamId, frame); + } + catch (Throwable x) + { + LOG.info("failure while notifying listener {}", listener, x); + } } private enum State diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/GoAwayBodyParser.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/GoAwayBodyParser.java index 7f1e9ba65ea..2ca99ed55e5 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/GoAwayBodyParser.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/GoAwayBodyParser.java @@ -15,17 +15,15 @@ package org.eclipse.jetty.http3.internal.parser; import java.nio.ByteBuffer; -import org.eclipse.jetty.http3.frames.Frame; - public class GoAwayBodyParser extends BodyParser { - public GoAwayBodyParser(HeaderParser headerParser) + public GoAwayBodyParser(HeaderParser headerParser, ParserListener listener) { - super(1, headerParser); + super(headerParser, listener); } @Override - public Frame parse(ByteBuffer buffer) + public boolean parse(ByteBuffer buffer) { throw new UnsupportedOperationException(); } diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/HeadersBodyParser.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/HeadersBodyParser.java index 4c2d6f282da..faf50706ed5 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/HeadersBodyParser.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/HeadersBodyParser.java @@ -16,10 +16,10 @@ package org.eclipse.jetty.http3.internal.parser; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; +import java.util.function.BooleanSupplier; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http3.ErrorCode; -import org.eclipse.jetty.http3.frames.Frame; import org.eclipse.jetty.http3.frames.HeadersFrame; import org.eclipse.jetty.http3.qpack.QpackDecoder; import org.eclipse.jetty.http3.qpack.QpackException; @@ -32,14 +32,17 @@ public class HeadersBodyParser extends BodyParser private static final Logger LOG = LoggerFactory.getLogger(HeadersBodyParser.class); private final ListParses the given {@code buffer} bytes and returns parsed frames.
+ *Parses the given {@code buffer} bytes and emit events to a {@link ParserListener}.
* * @param buffer the buffer to parse - * @return a parsed frame, or null if not enough bytes were provided to parse a frame */ - public Frame parse(ByteBuffer buffer) throws ParseException + public void parse(ByteBuffer buffer) { try { @@ -72,7 +71,7 @@ public class MessageParser state = State.BODY; break; } - return null; + return; } case BODY: { @@ -86,27 +85,25 @@ public class MessageParser // Unknown frame types must be ignored. if (LOG.isDebugEnabled()) LOG.debug("Ignoring unknown frame type {}", Integer.toHexString(frameType)); - Frame frame = unknownBodyParser.parse(buffer); - if (frame == null) - return null; - reset(); - break; + if (!unknownBodyParser.parse(buffer)) + return; } else { - Frame frame; if (headerParser.getFrameLength() == 0) - frame = bodyParser.emptyBody(buffer); - else - frame = bodyParser.parse(buffer); - if (frame != null) { - if (LOG.isDebugEnabled()) - LOG.debug("Parsed {} frame body from {}", FrameType.from(frameType), buffer); - reset(); + bodyParser.emptyBody(buffer); } - return frame; + else + { + if (!bodyParser.parse(buffer)) + return; + } + if (LOG.isDebugEnabled()) + LOG.debug("Parsed {} frame body from {}", FrameType.from(frameType), buffer); } + reset(); + break; } default: { @@ -115,22 +112,20 @@ public class MessageParser } } } - catch (ParseException x) - { - if (LOG.isDebugEnabled()) - LOG.debug("parse failed", x); - buffer.clear(); - throw x; - } catch (Throwable x) { if (LOG.isDebugEnabled()) LOG.debug("parse failed", x); buffer.clear(); - throw new ParseException(ErrorCode.INTERNAL_ERROR.code(), "parser_error", true, x); + connectionFailure(buffer, ErrorCode.INTERNAL_ERROR.code(), "parser_error"); } } + private void connectionFailure(ByteBuffer buffer, int error, String reason) + { + unknownBodyParser.sessionFailure(buffer, error, reason); + } + private enum State { HEADER, BODY diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/ParseException.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/ParseException.java deleted file mode 100644 index 12b40d3e12a..00000000000 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/ParseException.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.eclipse.jetty.http3.internal.parser; - -public class ParseException extends Exception -{ - private final int error; - private final boolean fatal; - - public ParseException(int error, String message) - { - this(error, message, false); - } - - public ParseException(int error, String message, boolean fatal) - { - this(error, message, fatal, null); - } - - public ParseException(int error, String message, boolean fatal, Throwable cause) - { - super(message, cause); - this.error = error; - this.fatal = fatal; - } - - public int getErrorCode() - { - return error; - } - - public boolean isFatal() - { - return fatal; - } -} diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/PushPromiseBodyParser.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/PushPromiseBodyParser.java index ffde5464795..9d8dd6181f5 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/PushPromiseBodyParser.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/PushPromiseBodyParser.java @@ -15,17 +15,15 @@ package org.eclipse.jetty.http3.internal.parser; import java.nio.ByteBuffer; -import org.eclipse.jetty.http3.frames.Frame; - public class PushPromiseBodyParser extends BodyParser { - public PushPromiseBodyParser(HeaderParser headerParser) + public PushPromiseBodyParser(HeaderParser headerParser, ParserListener listener) { - super(1, headerParser); + super(headerParser, listener); } @Override - public Frame parse(ByteBuffer buffer) + public boolean parse(ByteBuffer buffer) { throw new UnsupportedOperationException(); } diff --git a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/SettingsBodyParser.java b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/SettingsBodyParser.java index 385e40d0868..673723a0e14 100644 --- a/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/SettingsBodyParser.java +++ b/jetty-http3/http3-common/src/main/java/org/eclipse/jetty/http3/internal/parser/SettingsBodyParser.java @@ -18,7 +18,6 @@ import java.util.LinkedHashMap; import java.util.Map; import org.eclipse.jetty.http3.ErrorCode; -import org.eclipse.jetty.http3.frames.Frame; import org.eclipse.jetty.http3.frames.SettingsFrame; import org.eclipse.jetty.http3.internal.VarLenInt; @@ -30,9 +29,9 @@ public class SettingsBodyParser extends BodyParser private long key; private Map