public void handleEvent(final StreamConnection channel, PooledByteBuffer buffer) { if (UndertowLogger.REQUEST_LOGGER.isTraceEnabled()) { UndertowLogger.REQUEST_LOGGER.tracef("Opened HTTP/2 connection with %s", channel.getPeerAddress()); } //cool, we have a Http2 connection. Http2Channel http2Channel = new Http2Channel(channel, protocol, bufferPool, buffer, false, false, undertowOptions); Integer idleTimeout = undertowOptions.get(UndertowOptions.IDLE_TIMEOUT); if (idleTimeout != null && idleTimeout > 0) { http2Channel.setIdleTimeout(idleTimeout); } if(statisticsEnabled) { channel.getSinkChannel().setConduit(new BytesSentStreamSinkConduit(channel.getSinkChannel().getConduit(), connectorStatistics.sentAccumulator())); channel.getSourceChannel().setConduit(new BytesReceivedStreamSourceConduit(channel.getSourceChannel().getConduit(), connectorStatistics.receivedAccumulator())); connectorStatistics.incrementConnectionCount(); http2Channel.addCloseTask(closeTask); } connections.add(http2Channel); http2Channel.addCloseTask(new ChannelListener<Http2Channel>() { @Override public void handleEvent(Http2Channel channel) { connections.remove(channel); } }); http2Channel.getReceiveSetter().set(new Http2ReceiveListener(rootHandler, getUndertowOptions(), bufferSize, connectorStatistics)); http2Channel.resumeReceives(); }
@Override public <T> void addToAttachmentList(AttachmentKey<AttachmentList<T>> key, T value) { channel.addToAttachmentList(key, value); }
@Override protected AbstractHttp2StreamSourceChannel createChannel(FrameHeaderData frameHeaderData, PooledByteBuffer frameData) throws IOException { AbstractHttp2StreamSourceChannel channel = createChannelImpl(frameHeaderData, frameData); if(channel instanceof Http2StreamSourceChannel) { if (parseTimeoutUpdater != null) { if (channel != null) { parseTimeoutUpdater.requestStarted(); } else if (currentStreams.isEmpty()) { parseTimeoutUpdater.failedParse(); } } } return channel; }
private void sendSettingsAck() { if(!initialSettingsSent) { sendSettings(); initialSettingsSent = true; } Http2SettingsStreamSinkChannel stream = new Http2SettingsStreamSinkChannel(this); flushChannelIgnoreFailure(stream); }
public Http2ClientConnection(Http2Channel http2Channel, boolean initialUpgradeRequest, String defaultHost, ClientStatistics clientStatistics, boolean secure) { this.http2Channel = http2Channel; this.defaultHost = defaultHost; this.clientStatistics = clientStatistics; this.secure = secure; http2Channel.getReceiveSetter().set(new Http2ReceiveListener()); http2Channel.resumeReceives(); http2Channel.addCloseTask(closeTask); this.initialUpgradeRequest = initialUpgradeRequest; }
public void sendRstStream(int streamId, int statusCode) { if(!isOpen()) { //no point sending if the channel is closed return; } handleRstStream(streamId); if(UndertowLogger.REQUEST_IO_LOGGER.isDebugEnabled()) { UndertowLogger.REQUEST_IO_LOGGER.debugf(new ClosedChannelException(), "Sending rststream on channel %s stream %s", this, streamId); } Http2RstStreamSinkChannel channel = new Http2RstStreamSinkChannel(this, streamId, statusCode); flushChannelIgnoreFailure(channel); }
private boolean doHttp2PriRead(StreamConnection connection, ByteBuffer buffer, HttpServerConnection serverConnection, PooledByteBuffer extraData) throws IOException { if(buffer.hasRemaining()) { int res = connection.getSourceChannel().read(buffer); if (res == -1) { return true; //fail } if (buffer.hasRemaining()) { return false; } } buffer.flip(); for(int i = 0; i < PRI_EXPECTED.length; ++i) { if(buffer.get() != PRI_EXPECTED[i]) { throw UndertowMessages.MESSAGES.http2PriRequestFailed(); } } Http2Channel channel = new Http2Channel(connection, null, serverConnection.getByteBufferPool(), extraData, false, false, false, serverConnection.getUndertowOptions()); Http2ReceiveListener receiveListener = new Http2ReceiveListener(serverConnection.getRootHandler(), serverConnection.getUndertowOptions(), serverConnection.getBufferSize(), null); channel.getReceiveSetter().set(receiveListener); channel.resumeReceives(); return true; } }
sendPreface(); prefaceCount = PREFACE_BYTES.length; sendSettings(); initialSettingsSent = true; if(fromUpgrade) { sendSettings(); initialSettingsSent = true; headerParser.length = initialOtherSideSettings.remaining(); parser.parse(initialOtherSideSettings, headerParser); updateSettings(parser.getSettings()); } catch (Throwable e) { IoUtils.safeClose(connectedStreamChannel); this.addCloseTask(new ChannelListener<Http2Channel>() { @Override public void handleEvent(Http2Channel channel) {
public synchronized Http2HeadersStreamSinkChannel sendPushPromise(int associatedStreamId, HeaderMap requestHeaders, HeaderMap responseHeaders) throws IOException { if (!isOpen()) { throw UndertowMessages.MESSAGES.channelIsClosed(); } if (isClient()) { throw UndertowMessages.MESSAGES.pushPromiseCanOnlyBeCreatedByServer(); } sendConcurrentStreamsAtomicUpdater.incrementAndGet(this); if(sendMaxConcurrentStreams > 0 && sendConcurrentStreams > sendMaxConcurrentStreams) { throw UndertowMessages.MESSAGES.streamLimitExceeded(); } int streamId = streamIdCounter; streamIdCounter += 2; Http2PushPromiseStreamSinkChannel pushPromise = new Http2PushPromiseStreamSinkChannel(this, requestHeaders, associatedStreamId, streamId); flushChannel(pushPromise); Http2HeadersStreamSinkChannel http2SynStreamStreamSinkChannel = new Http2HeadersStreamSinkChannel(this, streamId, responseHeaders); currentStreams.put(streamId, new StreamHolder(http2SynStreamStreamSinkChannel)); return http2SynStreamStreamSinkChannel; }
private void sendSettings() { List<Http2Setting> settings = new ArrayList<>(); settings.add(new Http2Setting(Http2Setting.SETTINGS_HEADER_TABLE_SIZE, encoderHeaderTableSize)); if(isClient()) { settings.add(new Http2Setting(Http2Setting.SETTINGS_ENABLE_PUSH, pushEnabled ? 1 : 0)); } settings.add(new Http2Setting(Http2Setting.SETTINGS_MAX_FRAME_SIZE, receiveMaxFrameSize)); settings.add(new Http2Setting(Http2Setting.SETTINGS_INITIAL_WINDOW_SIZE, initialReceiveWindowSize)); if(maxHeaderListSize > 0) { settings.add(new Http2Setting(Http2Setting.SETTINGS_MAX_HEADER_LIST_SIZE, maxHeaderListSize)); } if(receiveMaxConcurrentStreams > 0) { settings.add(new Http2Setting(Http2Setting.SETTINGS_MAX_CONCURRENT_STREAMS, receiveMaxConcurrentStreams)); } Http2SettingsStreamSinkChannel stream = new Http2SettingsStreamSinkChannel(this, settings); flushChannelIgnoreFailure(stream); }
return; listener.completed(new Http2ClientConnection(new Http2Channel(connection, null, bufferPool, null, true, false, options), false, defaultHost, clientStatistics, false)); } catch (Throwable t) { IOException e = t instanceof IOException ? (IOException) t : new IOException(t); return; listener.completed(new Http2ClientConnection(new Http2Channel(connection, null, bufferPool, null, true, false, options), false, defaultHost, clientStatistics, false)); } catch (Throwable t) { IOException e = t instanceof IOException ? (IOException) t : new IOException(t);
@Override public void sendRequest(ClientRequest request, ClientCallback<ClientExchange> clientCallback) { if(!http2Channel.isOpen()) { clientCallback.failed(new ClosedChannelException()); return; sinkChannel = http2Channel.createStream(request.getRequestHeaders()); } catch (Throwable t) { IOException e = t instanceof IOException ? (IOException) t : new IOException(t);
public void sendUpdateWindowSize(int streamId, int delta) throws IOException { Http2WindowUpdateStreamSinkChannel windowUpdateStreamSinkChannel = new Http2WindowUpdateStreamSinkChannel(this, streamId, delta); flushChannel(windowUpdateStreamSinkChannel); }
@Override public void addCloseListener(final CloseListener listener) { channel.addCloseTask(new ChannelListener<Http2Channel>() { @Override public void handleEvent(Http2Channel channel) { listener.closed(Http2ServerConnection.this); } }); }
private void sendPreface() { Http2PrefaceStreamSinkChannel preface = new Http2PrefaceStreamSinkChannel(this); flushChannelIgnoreFailure(preface); } @Override
@Override public <T> List<T> getAttachmentList(AttachmentKey<? extends List<T>> key) { return channel.getAttachmentList(key); }
@Override public <T> T getAttachment(AttachmentKey<T> key) { return channel.getAttachment(key); }
Http2HeadersStreamSinkChannel sink = channel.createInitialUpgradeResponseStream(); final Http2ServerConnection connection = new Http2ServerConnection(channel, sink, undertowOptions, bufferSize, rootHandler);
public Http2ClientConnection(Http2Channel http2Channel, ClientCallback<ClientExchange> upgradeReadyCallback, ClientRequest clientRequest, String defaultHost, ClientStatistics clientStatistics, boolean secure) { this.http2Channel = http2Channel; this.defaultHost = defaultHost; this.clientStatistics = clientStatistics; this.secure = secure; http2Channel.getReceiveSetter().set(new Http2ReceiveListener()); http2Channel.resumeReceives(); http2Channel.addCloseTask(closeTask); this.initialUpgradeRequest = false; Http2ClientExchange exchange = new Http2ClientExchange(this, null, clientRequest); exchange.setResponseListener(upgradeReadyCallback); currentExchanges.put(1, exchange); }
@Override public void handleUpgrade(StreamConnection streamConnection, HttpServerExchange exchange) { OptionMap undertowOptions = exchange.getConnection().getUndertowOptions(); Http2Channel channel = new Http2Channel(streamConnection, upgrade, exchange.getConnection().getByteBufferPool(), null, false, true, true, settingsFrame, undertowOptions); Http2ReceiveListener receiveListener = new Http2ReceiveListener(new HttpHandler() { @Override public void handleRequest(HttpServerExchange exchange) throws Exception { //if this header is present we don't actually process the rest of the handler chain //as the request was only to create the initial request if(exchange.getRequestHeaders().contains("X-HTTP2-connect-only")) { exchange.endExchange(); return; } exchange.setProtocol(Protocols.HTTP_2_0); next.handleRequest(exchange); } }, undertowOptions, exchange.getConnection().getBufferSize(), null); channel.getReceiveSetter().set(receiveListener); receiveListener.handleInitialRequest(exchange, channel, data); channel.resumeReceives(); } });