Http2FrameCodec(Http2ConnectionEncoder encoder, Http2ConnectionDecoder decoder, Http2Settings initialSettings) { super(decoder, encoder, initialSettings); decoder.frameListener(new FrameListener()); connection().addListener(new ConnectionListener()); connection().remote().flowController().listener(new Http2RemoteFlowControllerListener()); streamKey = connection().newKey(); upgradeKey = connection().newKey(); initialFlowControlWindowSize = initialSettings.initialWindowSize(); }
protected Http2ConnectionHandler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings) { this.initialSettings = checkNotNull(initialSettings, "initialSettings"); this.decoder = checkNotNull(decoder, "decoder"); this.encoder = checkNotNull(encoder, "encoder"); if (encoder.connection() != decoder.connection()) { throw new IllegalArgumentException("Encoder and Decoder do not share the same connection object"); } }
public void channelInactive(ChannelHandlerContext ctx) throws Exception { // Connection has terminated, close the encoder and decoder. encoder().close(); decoder().close(); // We need to remove all streams (not just the active ones). // See https://github.com/netty/netty/issues/4838. connection().close(ctx.voidPromise()); }
@Override public void onSettingsRead(ChannelHandlerContext ctx, Http2Settings settings) throws Http2Exception { connection = connectionFactory.apply(this); if (useDecompressor) { decoder().frameListener(new DelegatingDecompressorFrameListener(decoder().connection(), connection)); } else { decoder().frameListener(connection); } connection.onSettingsRead(ctx, settings); if (addHandler != null) { addHandler.handle(connection); } }
@Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { // Initialize the encoder, decoder, flow controllers, and internal state. encoder.lifecycleManager(this); decoder.lifecycleManager(this); encoder.flowController().channelHandlerContext(ctx); decoder.flowController().channelHandlerContext(ctx); byteDecoder = new PrefaceDecoder(ctx); }
private T buildFromCodec(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder) { final T handler; try { // Call the abstract build method handler = build(decoder, encoder, initialSettings); } catch (Throwable t) { encoder.close(); decoder.close(); throw new IllegalStateException("failed to build a Http2ConnectionHandler", t); } // Setup post build options handler.gracefulShutdownTimeoutMillis(gracefulShutdownTimeoutMillis); if (handler.decoder().frameListener() == null) { handler.decoder().frameListener(frameListener); } return handler; }
/** * Consume {@code numBytes} for {@code stream} in the flow controller, this must be called from event loop. */ void consume(Http2Stream stream, int numBytes) { try { boolean windowUpdateSent = decoder().flowController().consumeBytes(stream, numBytes); if (windowUpdateSent) { chctx.channel().flush(); } } catch (Http2Exception e) { onError(chctx, true, e); } }
protected void updateSettings(Http2Settings settingsUpdate, Handler<AsyncResult<Void>> completionHandler) { Http2Settings current = handler.decoder().localSettings(); for (Map.Entry<Character, Long> entry : current.entrySet()) { Character key = entry.getKey(); if (Objects.equals(settingsUpdate.get(key), entry.getValue())) { settingsUpdate.remove(key); } } Handler<Void> pending = v -> { synchronized (Http2ConnectionBase.this) { localSettings.putAll(settingsUpdate); } if (completionHandler != null) { completionHandler.handle(Future.succeededFuture()); } }; updateSettingsHandlers.add(pending); handler.writeSettings(settingsUpdate).addListener(fut -> { if (!fut.isSuccess()) { synchronized (Http2ConnectionBase.this) { updateSettingsHandlers.remove(pending); } if (completionHandler != null) { completionHandler.handle(Future.failedFuture(fut.cause())); } } }); }
/** * Converts the current settings for the handler to the Base64-encoded representation used in * the HTTP2-Settings upgrade header. */ private CharSequence getSettingsHeaderValue(ChannelHandlerContext ctx) { ByteBuf buf = null; ByteBuf encodedBuf = null; try { // Get the local settings for the handler. Http2Settings settings = connectionHandler.decoder().localSettings(); // Serialize the payload of the SETTINGS frame. int payloadLength = SETTING_ENTRY_LENGTH * settings.size(); buf = ctx.alloc().buffer(payloadLength); for (CharObjectMap.PrimitiveEntry<Long> entry : settings.entries()) { buf.writeChar(entry.key()); buf.writeInt(entry.value().intValue()); } // Base64 encode the payload and then convert to a string for the header. encodedBuf = Base64.encode(buf, URL_SAFE); return encodedBuf.toString(UTF_8); } finally { release(buf); release(encodedBuf); } } }
try { onUpgradeEvent(ctx, upgrade.retain()); Http2Stream stream = connection().stream(HTTP_UPGRADE_STREAM_ID); if (stream.getProperty(streamKey) == null) { stream.setProperty(upgradeKey, true); InboundHttpToHttp2Adapter.handle( ctx, connection(), decoder().frameListener(), upgrade.upgradeRequest().retain()); } finally { upgrade.release();
/** * Handles the client-side (cleartext) upgrade from HTTP to HTTP/2. * Reserves local stream 1 for the HTTP/2 response. */ public void onHttpClientUpgrade() throws Http2Exception { if (connection().isServer()) { throw connectionError(PROTOCOL_ERROR, "Client-side HTTP upgrade requested for a server"); } if (!prefaceSent()) { // If the preface was not sent yet it most likely means the handler was not added to the pipeline before // calling this method. throw connectionError(INTERNAL_ERROR, "HTTP upgrade must occur after preface was sent"); } if (decoder.prefaceReceived()) { throw connectionError(PROTOCOL_ERROR, "HTTP upgrade must occur before HTTP/2 preface is received"); } // Create a local stream used for the HTTP cleartext upgrade. connection().local().createStream(HTTP_UPGRADE_STREAM_ID, true); }
/** * Handles the server-side (cleartext) upgrade from HTTP to HTTP/2. * @param settings the settings for the remote endpoint. */ public void onHttpServerUpgrade(Http2Settings settings) throws Http2Exception { if (!connection().isServer()) { throw connectionError(PROTOCOL_ERROR, "Server-side HTTP upgrade requested for a client"); } if (!prefaceSent()) { // If the preface was not sent yet it most likely means the handler was not added to the pipeline before // calling this method. throw connectionError(INTERNAL_ERROR, "HTTP upgrade must occur after preface was sent"); } if (decoder.prefaceReceived()) { throw connectionError(PROTOCOL_ERROR, "HTTP upgrade must occur before HTTP/2 preface is received"); } // Apply the settings but no ACK is necessary. encoder.remoteSettings(settings); // Create a stream in the half-closed state. connection().remote().createStream(HTTP_UPGRADE_STREAM_ID, true); }
Http2ServerConnectionHandler(Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings, Channel channel, ServerConfig config, GracefulShutdownSupport gracefulShutdownSupport) { super(decoder, encoder, initialSettings); this.gracefulShutdownSupport = gracefulShutdownSupport; requestDecoder = new Http2RequestDecoder(config, channel, encoder()); connection().addListener(requestDecoder); decoder().frameListener(requestDecoder); // Setup post build options final long timeout = config.idleTimeoutMillis(); if (timeout > 0) { gracefulShutdownTimeoutMillis(timeout); } else { // Timeout disabled gracefulShutdownTimeoutMillis(-1); } }
@Override public Http2FrameListener frameListener() { return delegate.frameListener(); }
@Override public HttpConnection setWindowSize(int windowSize) { try { Http2Stream stream = handler.encoder().connection().connectionStream(); int delta = windowSize - this.windowSize; handler.decoder().flowController().incrementWindowSize(stream, delta); this.windowSize = windowSize; return this; } catch (Http2Exception e) { throw new VertxException(e); } }
@Override public Http2Connection connection() { return delegate.connection(); }
@Override public void decodeFrame(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Http2Exception { delegate.decodeFrame(ctx, in, out); }
@Override public void close() { delegate.close(); } }
@Override public Http2LocalFlowController flowController() { return delegate.flowController(); }
@Override public Http2Settings localSettings() { return delegate.localSettings(); }