public RawFrame createResetStream(final int streamId, final int code) { Args.positive(streamId, "Stream id"); final ByteBuffer payload = ByteBuffer.allocate(4); payload.putInt(code); payload.flip(); return new RawFrame(FrameType.RST_STREAM.getValue(), 0, streamId, payload); }
public void write(final RawFrame frame, final WritableByteChannel channel) throws IOException { Args.notNull(frame, "Frame"); final ByteBuffer payload = frame.getPayload(); if (payload != null && payload.remaining() > maxFramePayloadSize) { throw new H2ConnectionException(H2Error.FRAME_SIZE_ERROR, "Frame size exceeds maximum"); } buffer.putInt((payload != null ? payload.remaining() << 8 : 0) | (frame.getType() & 0xff)); buffer.put((byte) (frame.getFlags() & 0xff)); buffer.putInt(frame.getStreamId()); if (payload != null) { if (channel instanceof GatheringByteChannel) { buffer.flip(); ((GatheringByteChannel) channel).write(new ByteBuffer[]{buffer, payload}); buffer.compact(); if (payload.hasRemaining()) { buffer.put(payload); } } else { buffer.put(payload); } } flush(channel); metrics.incrementFramesTransferred(); }
public boolean isPadded() { return isFlagSet(FrameFlag.PADDED); }
private void consumeFrame(final RawFrame frame) throws HttpException, IOException { final FrameType frameType = FrameType.valueOf(frame.getType()); final int streamId = frame.getStreamId(); if (continuation != null && frameType != FrameType.CONTINUATION) { throw new H2ConnectionException(H2Error.PROTOCOL_ERROR, "CONTINUATION frame expected"); final ByteBuffer payload = frame.getPayload(); if (payload == null || payload.remaining() != 4) { throw new H2ConnectionException(H2Error.FRAME_SIZE_ERROR, "Invalid WINDOW_UPDATE frame payload"); final ByteBuffer payload = frame.getPayload(); if (payload == null || payload.remaining() != 4) { throw new H2ConnectionException(H2Error.FRAME_SIZE_ERROR, "Invalid RST_STREAM frame payload"); final ByteBuffer ping = frame.getPayloadContent(); if (ping == null || ping.remaining() != 8) { throw new H2ConnectionException(H2Error.FRAME_SIZE_ERROR, "Invalid PING frame payload"); if (frame.isFlagSet(FrameFlag.ACK)) { final AsyncPingHandler pingHandler = pingHandlers.poll(); if (pingHandler != null) { if (frame.isFlagSet(FrameFlag.ACK)) { if (localSettingState == SettingsHandshake.TRANSMITTED) { localSettingState = SettingsHandshake.ACKED; final ByteBuffer payload = frame.getPayload(); if (payload != null) { if ((payload.remaining() % 6) != 0) {
public void printFrameInfo(final RawFrame frame, final Appendable appendable) throws IOException { appendable.append("stream ").append(Integer.toString(frame.getStreamId())).append(" frame: "); final FrameType type = FrameType.valueOf(frame.getType()); appendable.append(Objects.toString(type)) .append(" (0x").append(Integer.toHexString(frame.getType())).append("); flags: "); final int flags = frame.getFlags(); if (flags > 0) { switch (type) { appendable.append("(0x").append(Integer.toHexString(flags)).append("); length: ").append(Integer.toString(frame.getLength()));
public void printPayload(final RawFrame frame, final Appendable appendable) throws IOException { final FrameType type = FrameType.valueOf(frame.getType()); final ByteBuffer buf = frame.getPayloadContent(); if (buf != null) { printData(frame.getPayload(), appendable);
private void consumeHeaderFrame(final RawFrame frame, final Http2Stream stream) throws HttpException, IOException { final int streamId = stream.getId(); if (!frame.isFlagSet(FrameFlag.END_HEADERS)) { continuation = new Continuation(streamId, frame.getType(), frame.isFlagSet(FrameFlag.END_STREAM)); final ByteBuffer payload = frame.getPayloadContent(); if (frame.isFlagSet(FrameFlag.PRIORITY)) { throw new H2StreamResetException(H2Error.PROTOCOL_ERROR, "Stream refused"); if (frame.isFlagSet(FrameFlag.END_STREAM)) { stream.setRemoteEndStream();
private void consumeContinuationFrame(final RawFrame frame, final Http2Stream stream) throws HttpException, IOException { final int streamId = frame.getStreamId(); final ByteBuffer payload = frame.getPayload(); continuation.copyPayload(payload); if (frame.isFlagSet(FrameFlag.END_HEADERS)) { final List<Header> headers = hPackDecoder.decodeHeaders(continuation.getContent()); if (stream.isRemoteInitiated() && streamId > processedRemoteStreamId) {
private void consumeDataFrame(final RawFrame frame, final Http2Stream stream) throws HttpException, IOException { final int streamId = stream.getId(); final ByteBuffer payload = frame.getPayloadContent(); if (payload != null) { final int frameLength = frame.getLength(); final int streamWinSize = updateInputWindow(streamId, stream.getInputWindow(), -frameLength); if (streamWinSize < lowMark && !stream.isRemoteClosed()) { stream.produceInputCapacityUpdate(); } final int connWinSize = updateInputWindow(0, connInputWindow, -frameLength); if (connWinSize < lowMark) { final int chunk = Integer.MAX_VALUE - connWinSize; if (chunk > 0) { final RawFrame windowUpdateFrame = frameFactory.createWindowUpdate(0, chunk); commitFrame(windowUpdateFrame); updateInputWindow(0, connInputWindow, chunk); } } } if (stream.isRemoteClosed()) { throw new H2StreamResetException(H2Error.STREAM_CLOSED, "Stream already closed"); } if (stream.isLocalReset()) { return; } if (frame.isFlagSet(FrameFlag.END_STREAM)) { stream.setRemoteEndStream(); } stream.consumeData(payload); }
private void consumePushPromiseFrame(final RawFrame frame, final ByteBuffer payload, final Http2Stream promisedStream) throws HttpException, IOException { final int promisedStreamId = promisedStream.getId(); if (!frame.isFlagSet(FrameFlag.END_HEADERS)) { continuation = new Continuation(promisedStreamId, frame.getType(), true); } if (continuation == null) { final List<Header> headers = hPackDecoder.decodeHeaders(payload); if (promisedStreamId > processedRemoteStreamId) { processedRemoteStreamId = promisedStreamId; } if (streamListener != null) { streamListener.onHeaderInput(this, promisedStreamId, headers); } if (connState == ConnectionHandshake.GRACEFUL_SHUTDOWN) { throw new H2StreamResetException(H2Error.REFUSED_STREAM, "Stream refused"); } promisedStream.consumePromise(headers); } else { continuation.copyPayload(payload); } }
private void commitFrameInternal(final RawFrame frame) throws IOException { if (outputBuffer.isEmpty() && outputQueue.isEmpty()) { if (streamListener != null) { streamListener.onFrameOutput(this, frame.getStreamId(), frame); } outputBuffer.write(frame, ioSession.channel()); } else { outputQueue.addLast(frame); } ioSession.setEvent(SelectionKey.OP_WRITE); }
public ByteBuffer getPayloadContent() { if (payload != null) { if (isPadded()) { final ByteBuffer dup = payload.duplicate(); if (dup.remaining() == 0) { return null; } final int padding = dup.get() & 0xff; if (padding > dup.remaining()) { return null; } dup.limit(dup.limit() - padding); return dup; } return payload.duplicate(); } return null; }
public final void onInput() throws HttpException, IOException { if (connState == ConnectionHandshake.SHUTDOWN) { ioSession.clearEvent(SelectionKey.OP_READ); } else { RawFrame frame; while ((frame = inputBuffer.read(ioSession.channel())) != null) { if (streamListener != null) { streamListener.onFrameInput(this, frame.getStreamId(), frame); } consumeFrame(frame); } } }
return; final int type = frame.getType(); final long streamId = frame.getStreamId(); final int flags = frame.getFlags(); final ByteBuffer payload = frame.getPayload(); final int payloadLen = payload != null ? payload.remaining() : 0; if (payload != null && payload.remaining() > maxFramePayloadSize) {
public RawFrame createGoAway(final int lastStream, final H2Error error, final String message) { Args.notNegative(lastStream, "Last stream id"); final byte[] debugData = message != null ? message.getBytes(StandardCharsets.US_ASCII) : null; final ByteBuffer payload = ByteBuffer.allocate(8 + (debugData != null ? debugData.length : 0)); payload.putInt(lastStream); payload.putInt(error.getCode()); if (debugData != null) { payload.put(debugData); } payload.flip(); return new RawFrame(FrameType.GOAWAY.getValue(), 0, 0, payload); }
if (frame != null) { if (streamListener != null) { streamListener.onFrameOutput(this, frame.getStreamId(), frame);
public RawFrame createSettings(final H2Setting... settings) { final ByteBuffer payload = ByteBuffer.allocate(settings.length * 12); for (final H2Setting setting: settings) { payload.putShort((short) setting.getCode()); payload.putInt(setting.getValue()); } payload.flip(); return new RawFrame(FrameType.SETTINGS.getValue(), 0, 0, payload); }
public RawFrame createWindowUpdate(final int streamId, final int increment) { Args.notNegative(streamId, "Stream id"); Args.positive(increment, "Increment"); final ByteBuffer payload = ByteBuffer.allocate(4); payload.putInt(increment); payload.flip(); return new RawFrame(FrameType.WINDOW_UPDATE.getValue(), 0, streamId, payload); }
@Override public RawFrame createContinuation(final int streamId, final ByteBuffer payload, final boolean endHeaders) { Args.positive(streamId, "Stream id"); final int flags = (endHeaders ? FrameFlag.END_HEADERS.value : 0); return new RawFrame(FrameType.CONTINUATION.getValue(), flags, streamId, payload); }
@Override public RawFrame createPushPromise(final int streamId, final ByteBuffer payload, final boolean endHeaders) { Args.positive(streamId, "Stream id"); final int flags = (endHeaders ? FrameFlag.END_HEADERS.value : 0); return new RawFrame(FrameType.PUSH_PROMISE.getValue(), flags, streamId, payload); }