public void handleEventWithNoRunningRequest(final ConduitStreamSourceChannel channel) { PooledByteBuffer existing = connection.getExtraBytes(); if ((existing == null && connection.getOriginalSourceConduit().isReadShutdown()) || connection.getOriginalSinkConduit().isWriteShutdown()) { IoUtils.safeClose(connection); channel.suspendReads(); final PooledByteBuffer pooled = existing == null ? connection.getByteBufferPool().allocate() : existing; final ByteBuffer buffer = pooled.getBuffer(); boolean free = true; connection.setExtraBytes(null); } else { buffer.flip(); if (buffer.hasRemaining()) { free = false; connection.setExtraBytes(pooled); UndertowLogger.REQUEST_LOGGER.requestHeaderWasTooLarge(connection.getPeerAddress(), maxRequestSize); sendBadRequestAndClose(connection.getChannel(), null); return; httpServerExchange.setRequestScheme(connection.getSslSession() != null ? "https" : "http"); this.httpServerExchange = null; requestStateUpdater.set(this, 1); HttpString protocol = httpServerExchange.getProtocol(); if(protocol != Protocols.HTTP_1_1 && protocol != Protocols.HTTP_1_0 && protocol != Protocols.HTTP_0_9) { UndertowLogger.REQUEST_IO_LOGGER.debugf("Closing connection from %s due to unknown protocol %s", connection.getChannel().getPeerAddress(), protocol); sendBadRequestAndClose(connection.getChannel(), new IOException());
HttpReadListener(final HttpServerConnection connection, final HttpRequestParser parser, ConnectorStatisticsImpl connectorStatistics) { this.connection = connection; this.parser = parser; this.connectorStatistics = connectorStatistics; this.maxRequestSize = connection.getUndertowOptions().get(UndertowOptions.MAX_HEADER_SIZE, UndertowOptions.DEFAULT_MAX_HEADER_SIZE); this.maxEntitySize = connection.getUndertowOptions().get(UndertowOptions.MAX_ENTITY_SIZE, UndertowOptions.DEFAULT_MAX_ENTITY_SIZE); this.recordRequestStartTime = connection.getUndertowOptions().get(UndertowOptions.RECORD_REQUEST_START_TIME, false); this.requireHostHeader = connection.getUndertowOptions().get(UndertowOptions.REQUIRE_HOST_HTTP11, true); this.allowUnknownProtocols = connection.getUndertowOptions().get(UndertowOptions.ALLOW_UNKNOWN_PROTOCOLS, false); int requestParseTimeout = connection.getUndertowOptions().get(UndertowOptions.REQUEST_PARSE_TIMEOUT, -1); int requestIdleTimeout = connection.getUndertowOptions().get(UndertowOptions.NO_REQUEST_TIMEOUT, -1); if(requestIdleTimeout < 0 && requestParseTimeout < 0) { this.parseTimeoutUpdater = null; } else { this.parseTimeoutUpdater = new ParseTimeoutUpdater(connection, requestParseTimeout, requestIdleTimeout); connection.addCloseListener(parseTimeoutUpdater); } state = new ParseState(connection.getUndertowOptions().get(UndertowOptions.HTTP_HEADERS_CACHE_SIZE, UndertowOptions.DEFAULT_HTTP_HEADERS_CACHE_SIZE)); }
public void exchangeComplete(final HttpServerExchange exchange) { connection.clearChannel(); connection.setCurrentExchange(null); final HttpServerConnection connection = this.connection; if (exchange.isPersistent() && !isUpgradeOrConnect(exchange)) { final StreamConnection channel = connection.getChannel(); if (connection.getExtraBytes() == null) { } else { while (true) { if (connection.getOriginalSourceConduit().isReadShutdown() || connection.getOriginalSinkConduit().isWriteShutdown()) { channel.getSourceChannel().suspendReads(); channel.getSinkChannel().suspendWrites(); } else { while (true) { if (connection.getOriginalSinkConduit().isWriteShutdown()) { channel.getSourceChannel().suspendReads(); channel.getSinkChannel().suspendWrites(); ConnectionUtils.cleanClose(connection.getChannel(), connection); } else { if (connection.getExtraBytes() != null) { connection.getChannel().getSourceChannel().setConduit(new ReadDataStreamSourceConduit(connection.getChannel().getSourceChannel().getConduit(), connection)); if (!connection.getChannel().getSinkChannel().flush()) { connection.getChannel().getSinkChannel().setWriteListener(ChannelListeners.flushingChannelListener(new ChannelListener<ConduitStreamSinkChannel>() { @Override public void handleEvent(ConduitStreamSinkChannel conduitStreamSinkChannel) {
@Override public void handleEvent(ConduitStreamSinkChannel conduitStreamSinkChannel) { connection.getUpgradeListener().handleUpgrade(connection.getChannel(), exchange); } }, new ClosingChannelExceptionHandler<ConduitStreamSinkChannel>(connection)));
private boolean handleHttp2PriorKnowledge(PooledByteBuffer pooled, HttpServerExchange httpServerExchange) throws IOException { if(httpServerExchange.getRequestMethod().equals(PRI) && connection.getUndertowOptions().get(UndertowOptions.ENABLE_HTTP2, false)) { handleHttp2PriorKnowledge(connection.getChannel(), connection, pooled); return false; } else { sendBadRequestAndClose(connection.getChannel(), new IOException()); return true; } }
PipeliningBufferingStreamSinkConduit pipeliningBuffer = connection.getPipelineBuffer(); if (pipeliningBuffer != null) { pipeliningBuffer.setupPipelineBuffer(exchange); ConduitStreamSourceChannel sourceChannel = connection.getChannel().getSourceChannel(); sourceChannel.setConduit(connection.getReadDataStreamSourceConduit()); && connection.getExtraBytes() != null && pipeliningBuffer == null && connection.getUndertowOptions().get(UndertowOptions.BUFFER_PIPELINED_DATA, false)) { pipeliningBuffer = new PipeliningBufferingStreamSinkConduit(connection.getOriginalSinkConduit(), connection.getByteBufferPool()); connection.setPipelineBuffer(pipeliningBuffer); pipeliningBuffer.setupPipelineBuffer(exchange); if (!exchange.isRequestComplete() || connection.getExtraBytes() != null) {
ConduitStreamSourceChannel sourceChannel = ((HttpServerConnection) exchange.getConnection()).getChannel().getSourceChannel(); sourceChannel.setConduit(new ChunkedStreamSourceConduit(sourceChannel.getConduit(), exchange, chunkedDrainListener(exchange))); } else if (contentLengthHeader != null) { } else { ConduitStreamSourceChannel sourceChannel = ((HttpServerConnection) exchange.getConnection()).getChannel().getSourceChannel(); sourceChannel.setConduit(fixedLengthStreamSourceConduitWrapper(contentLength, sourceChannel.getConduit(), exchange)); if (connection.getExtraBytes() != null && pipeliningBuffer == null && connection.getUndertowOptions().get(UndertowOptions.BUFFER_PIPELINED_DATA, false)) { pipeliningBuffer = new PipeliningBufferingStreamSinkConduit(connection.getOriginalSinkConduit(), connection.getByteBufferPool()); connection.setPipelineBuffer(pipeliningBuffer); pipeliningBuffer.setupPipelineBuffer(exchange);
public void renegotiateNoRequest(HttpServerExchange exchange, SslClientAuthMode newAuthMode) throws IOException { AbstractServerConnection.ConduitState oldState = serverConnection.resetChannel(); try { SslClientAuthMode sslClientAuthMode = channel.getOption(Options.SSL_CLIENT_AUTH_MODE); channel.getSslSession().invalidate(); channel.startHandshake(); serverConnection.getOriginalSinkConduit().flush(); ByteBuffer buff = ByteBuffer.wrap(new byte[1]); long end = System.currentTimeMillis() + MAX_RENEGOTIATION_WAIT; while (!waiter.isDone() && serverConnection.isOpen() && System.currentTimeMillis() < end) { int read = serverConnection.getSourceChannel().read(buff); if (read != 0) { throw new SSLPeerUnverifiedException(""); serverConnection.getSourceChannel().awaitReadable(end - System.currentTimeMillis(), TimeUnit.MILLISECONDS); if(serverConnection.isOpen()) { IoUtils.safeClose(serverConnection); throw UndertowMessages.MESSAGES.rengotiationTimedOut(); serverConnection.restoreChannel(oldState);
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; } }
HttpServerConnection connection = new HttpServerConnection(channel, bufferPool, rootHandler, undertowOptions, bufferSize, statisticsEnabled ? connectorStatistics : null); HttpReadListener readListener = new HttpReadListener(connection, parser, statisticsEnabled ? connectorStatistics : null); connection.setExtraBytes(buffer); } else { buffer.close(); connection.addCloseListener(new ServerConnection.CloseListener() { @Override public void closed(ServerConnection c) { connection.setReadListener(readListener); readListener.newRequest(); channel.getSourceChannel().setReadListener(readListener);
void performFlush(final HttpServerExchange exchange, final HttpServerConnection connection) { try { final HttpServerConnection.ConduitState oldState = connection.resetChannel(); if (!flushPipelinedData()) { final StreamConnection channel = connection.getChannel(); channel.getSinkChannel().setWriteListener(new ChannelListener<Channel>() { @Override connection.getChannel().getSinkChannel().resumeWrites(); return; } else { connection.restoreChannel(oldState); connection.getReadListener().exchangeComplete(exchange); IoUtils.safeClose(connection.getChannel()); } catch (Throwable t) { UndertowLogger.REQUEST_IO_LOGGER.handleUnexpectedFailure(t); IoUtils.safeClose(connection.getChannel());
public void exchangeComplete(final HttpServerExchange exchange) { //if we ever fail to read then we flush the pipeline buffer //this relies on us always doing an eager read when starting a request, //rather than waiting to be notified of data being available final HttpServerConnection connection = (HttpServerConnection) exchange.getConnection(); if (connection.getExtraBytes() == null || exchange.isUpgrade()) { performFlush(exchange, connection); } else { connection.getReadListener().exchangeComplete(exchange); } }
private void bufferDone() { if(exchange == null) { return; } HttpServerConnection connection = (HttpServerConnection)exchange.getConnection(); if(connection.getExtraBytes() != null && connection.isOpen() && exchange.isRequestComplete()) { //if we are pipelining we hold onto the buffer pooledBuffer.getBuffer().clear(); } else { pooledBuffer.close(); pooledBuffer = null; this.exchange = null; } }
if (getExtraBytes() == null) { setExtraBytes(unget); } else { PooledByteBuffer eb = getExtraBytes(); ByteBuffer buf = eb.getBuffer(); final ByteBuffer ugBuffer = unget.getBuffer(); ugBuffer.flip(); eb.close(); setExtraBytes(unget); } else { unget.close(); final ByteBuffer newBuffer = ByteBuffer.wrap(data); setExtraBytes(new ImmediatePooledByteBuffer(newBuffer));
@Override public void run() { handleEvent(connection.getChannel().getSourceChannel()); }
private static ServerConnection createServerConnection(){ final StreamConnection streamConnection = createStreamConnection(); final OptionMap options = OptionMap.EMPTY; return new HttpServerConnection( streamConnection, null, null, options, 0, null ); }
@Override protected StreamConnection upgradeChannel() { clearChannel(); if (extraBytes != null) { channel.getSourceChannel().setConduit(new ReadDataStreamSourceConduit(channel.getSourceChannel().getConduit(), this)); } return channel; }
@Override public StreamSinkConduit wrap(ConduitFactory<StreamSinkConduit> factory, HttpServerExchange exchange) { ServerFixedLengthStreamSinkConduit fixed = new ServerFixedLengthStreamSinkConduit(new HttpResponseConduit(getSinkChannel().getConduit(), getByteBufferPool(), HttpServerConnection.this, exchange), false, false); fixed.reset(0, exchange); return fixed; } });
private static StreamSinkConduit handleFixedLength(HttpServerExchange exchange, boolean headRequest, StreamSinkConduit channel, HeaderMap responseHeaders, String contentLengthHeader, HttpServerConnection connection) { try { final long contentLength = parsePositiveLong(contentLengthHeader); if (headRequest) { return channel; } // fixed-length response ServerFixedLengthStreamSinkConduit fixed = connection.getFixedLengthStreamSinkConduit(); fixed.reset(contentLength, exchange); return fixed; } catch (NumberFormatException e) { //we just fix it for them responseHeaders.remove(Headers.CONTENT_LENGTH); } return null; }
public HttpServerConnection(StreamConnection channel, final ByteBufferPool bufferPool, final HttpHandler rootHandler, final OptionMap undertowOptions, final int bufferSize, final ConnectorStatisticsImpl connectorStatistics) { super(channel, bufferPool, rootHandler, undertowOptions, bufferSize); if (channel instanceof SslChannel) { sslSessionInfo = new ConnectionSSLSessionInfo(((SslChannel) channel), this); } this.responseConduit = new HttpResponseConduit(channel.getSinkChannel().getConduit(), bufferPool, this); fixedLengthStreamSinkConduit = new ServerFixedLengthStreamSinkConduit(responseConduit, false, false); readDataStreamSourceConduit = new ReadDataStreamSourceConduit(channel.getSourceChannel().getConduit(), this); //todo: do this without an allocation addCloseListener(new CloseListener() { @Override public void closed(ServerConnection connection) { if(connectorStatistics != null) { connectorStatistics.decrementConnectionCount(); } responseConduit.freeBuffers(); } }); }