private void readPushPromiseFrame( final ChannelHandlerContext ctx, ByteBuf payload, Http2FrameObserver observer) throws Http2Exception { final int pushPromiseStreamId = streamId; int padding = flags.readPaddingLength(payload); final int promisedStreamId = readUnsignedInt(payload); // Create a handler that invokes the observer when the header block is complete. headersContinuation = new HeadersContinuation() { @Override public int getStreamId() { return pushPromiseStreamId; } @Override public void processFragment( boolean endOfHeaders, ByteBuf fragment, int padding, Http2FrameObserver observer) throws Http2Exception { builder().addFragment(fragment, ctx.alloc(), endOfHeaders); if (endOfHeaders) { Http2Headers headers = builder().buildHeaders(); observer.onPushPromiseRead( ctx, pushPromiseStreamId, promisedStreamId, headers, padding); close(); } } }; // Process the initial fragment, invoking the observer's callback if end of headers. final ByteBuf fragment = payload.readSlice(payload.readableBytes() - padding); headersContinuation.processFragment(flags.endOfHeaders(), fragment, padding, observer); }
private void readContinuationFrame(ByteBuf payload, Http2FrameObserver observer) throws Http2Exception { int padding = flags.readPaddingLength(payload); // Process the initial fragment, invoking the observer's callback if end of headers. final ByteBuf continuationFragment = payload.readSlice(payload.readableBytes() - padding); headersContinuation.processFragment( flags.endOfHeaders(), continuationFragment, padding, observer); }
private void verifyDataFrame() throws Http2Exception { verifyNotProcessingHeaders(); verifyPayloadLength(payloadLength); if (!flags.isPaddingLengthValid()) { throw protocolError("Pad high is set but pad low is not"); } if (payloadLength < flags.getNumPaddingLengthBytes()) { throw protocolError("Frame length %d too small.", payloadLength); } }
private void verifyPushPromiseFrame() throws Http2Exception { verifyNotProcessingHeaders(); verifyPayloadLength(payloadLength); if (!flags.isPaddingLengthValid()) { throw protocolError("Pad high is set but pad low is not"); } // Subtract the length of the promised stream ID field, to determine the length of the // rest of the payload (header block fragment + payload). int lengthWithoutPromisedId = payloadLength - INT_FIELD_LENGTH; if (lengthWithoutPromisedId < flags.getNumPaddingLengthBytes()) { throw protocolError("Frame length %d too small for padding.", payloadLength); } }
private void verifyHeadersFrame() throws Http2Exception { verifyNotProcessingHeaders(); verifyPayloadLength(payloadLength); int lengthWithoutPriority = flags.getNumPaddingLengthBytes(); if (lengthWithoutPriority < 0) { throw protocolError("Frame length too small." + payloadLength); } if (!flags.isPaddingLengthValid()) { throw protocolError("Pad high is set but pad low is not"); } if (lengthWithoutPriority < flags.getNumPaddingLengthBytes()) { throw protocolError("Frame length %d too small for padding.", payloadLength); } }
private void readPingFrame( ChannelHandlerContext ctx, ByteBuf payload, Http2FrameObserver observer) throws Http2Exception { ByteBuf data = payload.readSlice(payload.readableBytes()); if (flags.ack()) { observer.onPingAckRead(ctx, data); } else { observer.onPingRead(ctx, data); } }
private void verifyContinuationFrame() throws Http2Exception { verifyPayloadLength(payloadLength); if (headersContinuation == null) { throw protocolError("Received %s frame but not currently processing headers.", frameType); } if (streamId != headersContinuation.getStreamId()) { throw protocolError( "Continuation stream ID does not match pending headers. " + "Expected %d, but received %d.", headersContinuation.getStreamId(), streamId); } if (!flags.isPaddingLengthValid()) { throw protocolError("Pad high is set but pad low is not"); } if (payloadLength < flags.getNumPaddingLengthBytes()) { throw protocolError("Frame length %d too small for padding.", payloadLength); } }
private void verifySettingsFrame() throws Http2Exception { verifyNotProcessingHeaders(); verifyPayloadLength(payloadLength); if (streamId != 0) { throw protocolError("A stream ID must be zero."); } if (flags.ack() && payloadLength > 0) { throw protocolError("Ack settings frame must have an empty payload."); } if (payloadLength % SETTING_ENTRY_LENGTH > 0) { throw protocolError("Frame length %d invalid.", payloadLength); } }
private void readDataFrame( ChannelHandlerContext ctx, ByteBuf payload, Http2FrameObserver observer) throws Http2Exception { int dataPadding = flags.readPaddingLength(payload); // Determine how much data there is to read by removing the trailing // padding. int dataLength = payload.readableBytes() - dataPadding; if (dataLength < 0) { throw protocolError("Frame payload too small for padding."); } ByteBuf data = payload.readSlice(dataLength); observer.onDataRead( ctx, streamId, data, dataPadding, flags.endOfStream(), flags.endOfSegment(), flags.compressed()); payload.skipBytes(payload.readableBytes()); }
private void readSettingsFrame( ChannelHandlerContext ctx, ByteBuf payload, Http2FrameObserver observer) throws Http2Exception { if (flags.ack()) { observer.onSettingsAckRead(ctx); } else { int numSettings = payloadLength / SETTING_ENTRY_LENGTH; Http2Settings settings = new Http2Settings(); for (int index = 0; index < numSettings; ++index) { short id = payload.readUnsignedByte(); long value = payload.readUnsignedInt(); switch (id) { case SETTINGS_HEADER_TABLE_SIZE: if (value < 0 || value > Integer.MAX_VALUE) { throw protocolError("Invalid value for HEADER_TABLE_SIZE: %d", value); } settings.maxHeaderTableSize((int) value); break; case SETTINGS_COMPRESS_DATA: if (value != 0 && value != 1) { throw protocolError("Invalid value for COMPRESS_DATA: %d", value); } settings.allowCompressedData(value == 1); break; case SETTINGS_ENABLE_PUSH: if (value != 0 && value != 1) { throw protocolError("Invalid value for ENABLE_PUSH: %d", value); } settings.pushEnabled(value == 1); break; case SETTINGS_INITIAL_WINDOW_SIZE: if (value < 0 || value > Integer.MAX_VALUE) { throw protocolError("Invalid value for INITIAL_WINDOW_SIZE: %d", value); } settings.initialWindowSize((int) value); break; case SETTINGS_MAX_CONCURRENT_STREAMS: if (value < 0 || value > Integer.MAX_VALUE) { throw protocolError("Invalid value for MAX_CONCURRENT_STREAMS: %d", value); } settings.maxConcurrentStreams((int) value); break; default: throw protocolError("Unsupport setting: %d", id); } } observer.onSettingsRead(ctx, settings); } }
private void readHeadersFrame( final ChannelHandlerContext ctx, ByteBuf payload, Http2FrameObserver observer) throws Http2Exception { final int headersStreamId = streamId; final Http2Flags headersFlags = flags; int padding = flags.readPaddingLength(payload); // The callback that is invoked is different depending on whether priority information // is present in the headers frame. if (flags.priorityPresent()) { long word1 = payload.readUnsignedInt(); final boolean exclusive = (word1 & 0x80000000L) > 0; final int streamDependency = (int) (word1 & 0x7FFFFFFFL); final short weight = (short) (payload.readUnsignedByte() + 1); final ByteBuf fragment = payload.readSlice(payload.readableBytes() - padding); // Create a handler that invokes the observer when the header block is complete. headersContinuation = new HeadersContinuation() { @Override public int getStreamId() { return headersStreamId; } @Override public void processFragment( boolean endOfHeaders, ByteBuf fragment, int padding, Http2FrameObserver observer) throws Http2Exception { builder().addFragment(fragment, ctx.alloc(), endOfHeaders); if (endOfHeaders) { Http2Headers headers = builder().buildHeaders(); observer.onHeadersRead( ctx, headersStreamId, headers, streamDependency, weight, exclusive, padding, headersFlags.endOfStream(), headersFlags.endOfSegment()); close(); } } }; // Process the initial fragment, invoking the observer's callback if end of headers. headersContinuation.processFragment(flags.endOfHeaders(), fragment, padding, observer); return; } // The priority fields are not present in the frame. Prepare a continuation that invokes // the observer callback without priority information. headersContinuation = new HeadersContinuation() { @Override public int getStreamId() { return headersStreamId; } @Override public void processFragment( boolean endOfHeaders, ByteBuf fragment, int padding, Http2FrameObserver observer) throws Http2Exception { builder().addFragment(fragment, ctx.alloc(), endOfHeaders); if (endOfHeaders) { Http2Headers headers = builder().buildHeaders(); observer.onHeadersRead( ctx, headersStreamId, headers, padding, headersFlags.endOfStream(), headersFlags.endOfSegment()); close(); } } }; // Process the initial fragment, invoking the observer's callback if end of headers. final ByteBuf fragment = payload.readSlice(payload.readableBytes() - padding); headersContinuation.processFragment(flags.endOfHeaders(), fragment, padding, observer); }